00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "accessors.h"
00031 #include "api.h"
00032 #include "bootstrapper.h"
00033 #include "compiler.h"
00034 #include "debug.h"
00035 #include "execution.h"
00036 #include "global-handles.h"
00037 #include "natives.h"
00038 #include "runtime.h"
00039
00040 namespace v8 { namespace internal {
00041
00042
00043 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
00044 Handle<JSArray> array) {
00045 CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray);
00046 }
00047
00048
00049 Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first,
00050 Handle<FixedArray> second) {
00051 CALL_HEAP_FUNCTION(first->UnionOfKeys(*second), FixedArray);
00052 }
00053
00054
00055 Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
00056 Handle<JSFunction> constructor,
00057 Handle<JSGlobalProxy> global) {
00058 CALL_HEAP_FUNCTION(Heap::ReinitializeJSGlobalProxy(*constructor, *global),
00059 JSGlobalProxy);
00060 }
00061
00062
00063 void SetExpectedNofProperties(Handle<JSFunction> func, int nof) {
00064 func->shared()->set_expected_nof_properties(nof);
00065 if (func->has_initial_map()) {
00066 Handle<Map> new_initial_map =
00067 Factory::CopyMapDropTransitions(Handle<Map>(func->initial_map()));
00068 new_initial_map->set_unused_property_fields(nof);
00069 func->set_initial_map(*new_initial_map);
00070 }
00071 }
00072
00073
00074 void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value) {
00075 CALL_HEAP_FUNCTION_VOID(func->SetPrototype(*value));
00076 }
00077
00078
00079 static int ExpectedNofPropertiesFromEstimate(int estimate) {
00080
00081
00082
00083 if (estimate == 0) return 4;
00084 return estimate + 2;
00085 }
00086
00087
00088 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
00089 int estimate) {
00090 shared->set_expected_nof_properties(
00091 ExpectedNofPropertiesFromEstimate(estimate));
00092 }
00093
00094
00095 void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func,
00096 int estimate) {
00097 SetExpectedNofProperties(
00098 func, ExpectedNofPropertiesFromEstimate(estimate));
00099 }
00100
00101
00102 void NormalizeProperties(Handle<JSObject> object) {
00103 CALL_HEAP_FUNCTION_VOID(object->NormalizeProperties());
00104 }
00105
00106
00107 void NormalizeElements(Handle<JSObject> object) {
00108 CALL_HEAP_FUNCTION_VOID(object->NormalizeElements());
00109 }
00110
00111
00112 void TransformToFastProperties(Handle<JSObject> object,
00113 int unused_property_fields) {
00114 CALL_HEAP_FUNCTION_VOID(
00115 object->TransformToFastProperties(unused_property_fields));
00116 }
00117
00118
00119 void FlattenString(Handle<String> string) {
00120 if (string->IsFlat()) return;
00121 CALL_HEAP_FUNCTION_VOID(string->Flatten());
00122 ASSERT(string->IsFlat());
00123 }
00124
00125
00126 Handle<Object> SetPrototype(Handle<JSFunction> function,
00127 Handle<Object> prototype) {
00128 CALL_HEAP_FUNCTION(Accessors::FunctionSetPrototype(*function,
00129 *prototype,
00130 NULL),
00131 Object);
00132 }
00133
00134
00135 Handle<Object> SetProperty(Handle<JSObject> object,
00136 Handle<String> key,
00137 Handle<Object> value,
00138 PropertyAttributes attributes) {
00139 CALL_HEAP_FUNCTION(object->SetProperty(*key, *value, attributes), Object);
00140 }
00141
00142
00143 Handle<Object> SetProperty(Handle<Object> object,
00144 Handle<Object> key,
00145 Handle<Object> value,
00146 PropertyAttributes attributes) {
00147 CALL_HEAP_FUNCTION(
00148 Runtime::SetObjectProperty(object, key, value, attributes), Object);
00149 }
00150
00151
00152 Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
00153 Handle<String> key,
00154 Handle<Object> value,
00155 PropertyAttributes attributes) {
00156 CALL_HEAP_FUNCTION(object->
00157 IgnoreAttributesAndSetLocalProperty(*key, *value, attributes), Object);
00158 }
00159
00160 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
00161 Handle<String> key,
00162 Handle<Object> value,
00163 PropertyAttributes attributes) {
00164 CALL_HEAP_FUNCTION(object->SetPropertyWithInterceptor(*key,
00165 *value,
00166 attributes),
00167 Object);
00168 }
00169
00170
00171 Handle<Object> GetProperty(Handle<JSObject> obj,
00172 const char* name) {
00173 Handle<String> str = Factory::LookupAsciiSymbol(name);
00174 CALL_HEAP_FUNCTION(obj->GetProperty(*str), Object);
00175 }
00176
00177
00178 Handle<Object> GetProperty(Handle<Object> obj,
00179 Handle<Object> key) {
00180 CALL_HEAP_FUNCTION(Runtime::GetObjectProperty(obj, key), Object);
00181 }
00182
00183
00184 Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
00185 Handle<JSObject> holder,
00186 Handle<String> name,
00187 PropertyAttributes* attributes) {
00188 CALL_HEAP_FUNCTION(holder->GetPropertyWithInterceptor(*receiver,
00189 *name,
00190 attributes),
00191 Object);
00192 }
00193
00194
00195 Handle<Object> GetPrototype(Handle<Object> obj) {
00196 Handle<Object> result(obj->GetPrototype());
00197 return result;
00198 }
00199
00200
00201 Handle<Object> DeleteElement(Handle<JSObject> obj,
00202 uint32_t index) {
00203 CALL_HEAP_FUNCTION(obj->DeleteElement(index), Object);
00204 }
00205
00206
00207 Handle<Object> DeleteProperty(Handle<JSObject> obj,
00208 Handle<String> prop) {
00209 CALL_HEAP_FUNCTION(obj->DeleteProperty(*prop), Object);
00210 }
00211
00212
00213 Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) {
00214 CALL_HEAP_FUNCTION(Heap::LookupSingleCharacterStringFromCode(index), Object);
00215 }
00216
00217
00218 Handle<String> SubString(Handle<String> str, int start, int end) {
00219 CALL_HEAP_FUNCTION(str->Slice(start, end), String);
00220 }
00221
00222
00223 Handle<Object> SetElement(Handle<JSObject> object,
00224 uint32_t index,
00225 Handle<Object> value) {
00226 CALL_HEAP_FUNCTION(object->SetElement(index, *value), Object);
00227 }
00228
00229
00230 Handle<JSObject> Copy(Handle<JSObject> obj) {
00231 CALL_HEAP_FUNCTION(Heap::CopyJSObject(*obj), JSObject);
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241 static void ClearWrapperCache(Persistent<v8::Value> handle, void*) {
00242 Handle<Object> cache = Utils::OpenHandle(*handle);
00243 JSValue* wrapper = JSValue::cast(*cache);
00244 Proxy* proxy = Script::cast(wrapper->value())->wrapper();
00245 ASSERT(proxy->proxy() == reinterpret_cast<Address>(cache.location()));
00246 proxy->set_proxy(0);
00247 GlobalHandles::Destroy(cache.location());
00248 Counters::script_wrappers.Decrement();
00249 }
00250
00251
00252 Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
00253 Handle<Object> cache(reinterpret_cast<Object**>(script->wrapper()->proxy()));
00254 if (!cache.is_null()) {
00255
00256 return Handle<JSValue>(JSValue::cast(*cache));
00257 }
00258
00259
00260 Counters::script_wrappers.Increment();
00261 Handle<JSFunction> constructor = Top::script_function();
00262 Handle<JSValue> result =
00263 Handle<JSValue>::cast(Factory::NewJSObject(constructor));
00264 result->set_value(*script);
00265
00266
00267
00268
00269 Handle<Object> handle = GlobalHandles::Create(*result);
00270 GlobalHandles::MakeWeak(handle.location(), NULL, &ClearWrapperCache);
00271 script->wrapper()->set_proxy(reinterpret_cast<Address>(handle.location()));
00272 return result;
00273 }
00274
00275
00276
00277 v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
00278 Handle<JSObject> object) {
00279 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
00280 Handle<Object> data(interceptor->data());
00281 v8::AccessorInfo info(
00282 v8::Utils::ToLocal(receiver),
00283 v8::Utils::ToLocal(data),
00284 v8::Utils::ToLocal(object));
00285 v8::Handle<v8::Array> result;
00286 if (!interceptor->enumerator()->IsUndefined()) {
00287 v8::NamedPropertyEnumerator enum_fun =
00288 v8::ToCData<v8::NamedPropertyEnumerator>(interceptor->enumerator());
00289 LOG(ApiObjectAccess("interceptor-named-enum", *object));
00290 {
00291
00292 VMState state(OTHER);
00293 result = enum_fun(info);
00294 }
00295 }
00296 return result;
00297 }
00298
00299
00300
00301 v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
00302 Handle<JSObject> object) {
00303 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
00304 Handle<Object> data(interceptor->data());
00305 v8::AccessorInfo info(
00306 v8::Utils::ToLocal(receiver),
00307 v8::Utils::ToLocal(data),
00308 v8::Utils::ToLocal(object));
00309 v8::Handle<v8::Array> result;
00310 if (!interceptor->enumerator()->IsUndefined()) {
00311 v8::IndexedPropertyEnumerator enum_fun =
00312 v8::ToCData<v8::IndexedPropertyEnumerator>(interceptor->enumerator());
00313 LOG(ApiObjectAccess("interceptor-indexed-enum", *object));
00314 {
00315
00316 VMState state(OTHER);
00317 result = enum_fun(info);
00318 }
00319 }
00320 return result;
00321 }
00322
00323
00324 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
00325 Handle<FixedArray> content = Factory::empty_fixed_array();
00326
00327 JSObject* arguments_boilerplate =
00328 Top::context()->global_context()->arguments_boilerplate();
00329 JSFunction* arguments_function =
00330 JSFunction::cast(arguments_boilerplate->map()->constructor());
00331 bool allow_enumeration = (object->map()->constructor() != arguments_function);
00332
00333
00334 if (allow_enumeration) {
00335 for (Handle<Object> p = object;
00336 *p != Heap::null_value();
00337 p = Handle<Object>(p->GetPrototype())) {
00338 Handle<JSObject> current(JSObject::cast(*p));
00339
00340
00341 if (current->IsAccessCheckNeeded() &&
00342 !Top::MayNamedAccess(*current, Heap::undefined_value(),
00343 v8::ACCESS_KEYS)) {
00344 Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS);
00345 break;
00346 }
00347
00348
00349 content = UnionOfKeys(content, GetEnumPropertyKeys(current));
00350
00351
00352 if (current->HasNamedInterceptor()) {
00353 v8::Handle<v8::Array> result =
00354 GetKeysForNamedInterceptor(object, current);
00355 if (!result.IsEmpty())
00356 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
00357 }
00358
00359
00360 Handle<FixedArray> element_keys =
00361 Factory::NewFixedArray(current->NumberOfEnumElements());
00362 current->GetEnumElementKeys(*element_keys);
00363 content = UnionOfKeys(content, element_keys);
00364
00365
00366 if (current->HasIndexedInterceptor()) {
00367 v8::Handle<v8::Array> result =
00368 GetKeysForIndexedInterceptor(object, current);
00369 if (!result.IsEmpty())
00370 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
00371 }
00372 }
00373 }
00374 return content;
00375 }
00376
00377
00378 Handle<JSArray> GetKeysFor(Handle<JSObject> object) {
00379 Counters::for_in.Increment();
00380 Handle<FixedArray> elements = GetKeysInFixedArrayFor(object);
00381 return Factory::NewJSArrayWithElements(elements);
00382 }
00383
00384
00385 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object) {
00386 int index = 0;
00387 if (object->HasFastProperties()) {
00388 if (object->map()->instance_descriptors()->HasEnumCache()) {
00389 Counters::enum_cache_hits.Increment();
00390 DescriptorArray* desc = object->map()->instance_descriptors();
00391 return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache()));
00392 }
00393 Counters::enum_cache_misses.Increment();
00394 int num_enum = object->NumberOfEnumProperties();
00395 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum);
00396 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum);
00397 for (DescriptorReader r(object->map()->instance_descriptors());
00398 !r.eos();
00399 r.advance()) {
00400 if (!r.IsTransition() && !r.IsDontEnum()) {
00401 (*storage)->set(index, r.GetKey());
00402 (*sort_array)->set(index, Smi::FromInt(r.GetDetails().index()));
00403 index++;
00404 }
00405 }
00406 (*storage)->SortPairs(*sort_array);
00407 Handle<FixedArray> bridge_storage =
00408 Factory::NewFixedArray(DescriptorArray::kEnumCacheBridgeLength);
00409 DescriptorArray* desc = object->map()->instance_descriptors();
00410 desc->SetEnumCache(*bridge_storage, *storage);
00411 ASSERT(storage->length() == index);
00412 return storage;
00413 } else {
00414 int num_enum = object->NumberOfEnumProperties();
00415 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum);
00416 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum);
00417 object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array);
00418 return storage;
00419 }
00420 }
00421
00422
00423 bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
00424 ClearExceptionFlag flag) {
00425
00426 ASSERT(!shared->is_compiled());
00427 bool result = Compiler::CompileLazy(shared);
00428 ASSERT(result != Top::has_pending_exception());
00429 if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
00430 return result;
00431 }
00432
00433
00434 bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
00435
00436 Handle<SharedFunctionInfo> shared(function->shared());
00437 return CompileLazyShared(shared, flag);
00438 }
00439
00440
00441 OptimizedObjectForAddingMultipleProperties::
00442 OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
00443 bool condition) {
00444 object_ = object;
00445 if (condition && object_->HasFastProperties()) {
00446
00447
00448 unused_property_fields_ = object->map()->unused_property_fields();
00449 NormalizeProperties(object_);
00450 has_been_transformed_ = true;
00451
00452 } else {
00453 has_been_transformed_ = false;
00454 }
00455 }
00456
00457
00458 OptimizedObjectForAddingMultipleProperties::
00459 ~OptimizedObjectForAddingMultipleProperties() {
00460
00461 if (has_been_transformed_) {
00462 TransformToFastProperties(object_, unused_property_fields_);
00463 }
00464 }
00465
00466
00467 void LoadLazy(Handle<JSFunction> fun, bool* pending_exception) {
00468 HandleScope scope;
00469 Handle<FixedArray> info(FixedArray::cast(fun->shared()->lazy_load_data()));
00470 int index = Smi::cast(info->get(0))->value();
00471 ASSERT(index >= 0);
00472 Handle<Context> compile_context(Context::cast(info->get(1)));
00473 Handle<Context> function_context(Context::cast(info->get(2)));
00474 Handle<Object> receiver(compile_context->global()->builtins());
00475
00476 Vector<const char> name = Natives::GetScriptName(index);
00477
00478 Handle<JSFunction> boilerplate;
00479
00480 if (!Bootstrapper::NativesCacheLookup(name, &boilerplate)) {
00481 Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
00482 Handle<String> script_name = Factory::NewStringFromAscii(name);
00483 bool allow_natives_syntax = FLAG_allow_natives_syntax;
00484 FLAG_allow_natives_syntax = true;
00485 boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL);
00486 FLAG_allow_natives_syntax = allow_natives_syntax;
00487
00488
00489
00490
00491 if (boilerplate.is_null()) {
00492 *pending_exception = true;
00493 return;
00494 }
00495 Bootstrapper::NativesCacheAdd(name, boilerplate);
00496 }
00497
00498
00499 ASSERT(!boilerplate.is_null());
00500
00501
00502
00503
00504 SaveContext save;
00505 if (!Debug::debug_context().is_null() &&
00506 Top::context() == *Debug::debug_context()) {
00507 Top::set_context(*compile_context);
00508 }
00509
00510
00511
00512 fun->shared()->set_lazy_load_data(Heap::undefined_value());
00513
00514
00515 Handle<JSFunction> script_fun(
00516 Factory::NewFunctionFromBoilerplate(boilerplate, function_context));
00517 Execution::Call(script_fun, receiver, 0, NULL, pending_exception);
00518
00519
00520 if (*pending_exception) fun->shared()->set_lazy_load_data(*info);
00521 }
00522
00523
00524 void SetupLazy(Handle<JSFunction> fun,
00525 int index,
00526 Handle<Context> compile_context,
00527 Handle<Context> function_context) {
00528 Handle<FixedArray> arr = Factory::NewFixedArray(3);
00529 arr->set(0, Smi::FromInt(index));
00530 arr->set(1, *compile_context);
00531 arr->set(2, *function_context);
00532 fun->shared()->set_lazy_load_data(*arr);
00533 }
00534
00535 } }