diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
commit | 33af2720f26c2b25bc7f75ce7eb454ff99db6d35 (patch) | |
tree | 9a38f0c96420edf503eebd6325dd8d2d8249f653 /deps/v8/src/bootstrapper.cc | |
parent | 6afdca885adeeeed9eef8cbb01c3d97af0bc084d (diff) | |
download | node-33af2720f26c2b25bc7f75ce7eb454ff99db6d35.tar.gz |
Upgrade V8 to 3.4.8
Diffstat (limited to 'deps/v8/src/bootstrapper.cc')
-rw-r--r-- | deps/v8/src/bootstrapper.cc | 1210 |
1 files changed, 764 insertions, 446 deletions
diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 415d2dd8c..8e34b9cf5 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -44,100 +44,60 @@ namespace v8 { namespace internal { -// A SourceCodeCache uses a FixedArray to store pairs of -// (AsciiString*, JSFunction*), mapping names of native code files -// (runtime.js, etc.) to precompiled functions. Instead of mapping -// names to functions it might make sense to let the JS2C tool -// generate an index for each native JS file. -class SourceCodeCache BASE_EMBEDDED { - public: - explicit SourceCodeCache(Script::Type type): type_(type), cache_(NULL) { } - - void Initialize(bool create_heap_objects) { - cache_ = create_heap_objects ? Heap::empty_fixed_array() : NULL; - } - - void Iterate(ObjectVisitor* v) { - v->VisitPointer(BitCast<Object**>(&cache_)); - } - - - bool Lookup(Vector<const char> name, Handle<SharedFunctionInfo>* handle) { - for (int i = 0; i < cache_->length(); i+=2) { - SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i)); - if (str->IsEqualTo(name)) { - *handle = Handle<SharedFunctionInfo>( - SharedFunctionInfo::cast(cache_->get(i + 1))); - return true; - } - } - return false; - } - - - void Add(Vector<const char> name, Handle<SharedFunctionInfo> shared) { - HandleScope scope; - int length = cache_->length(); - Handle<FixedArray> new_array = - Factory::NewFixedArray(length + 2, TENURED); - cache_->CopyTo(0, *new_array, 0, cache_->length()); - cache_ = *new_array; - Handle<String> str = Factory::NewStringFromAscii(name, TENURED); - cache_->set(length, *str); - cache_->set(length + 1, *shared); - Script::cast(shared->script())->set_type(Smi::FromInt(type_)); - } - - private: - Script::Type type_; - FixedArray* cache_; - DISALLOW_COPY_AND_ASSIGN(SourceCodeCache); -}; - -static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION); -// This is for delete, not delete[]. -static List<char*>* delete_these_non_arrays_on_tear_down = NULL; -// This is for delete[] -static List<char*>* delete_these_arrays_on_tear_down = NULL; - -NativesExternalStringResource::NativesExternalStringResource(const char* source) - : data_(source), length_(StrLength(source)) { - if (delete_these_non_arrays_on_tear_down == NULL) { - delete_these_non_arrays_on_tear_down = new List<char*>(2); +NativesExternalStringResource::NativesExternalStringResource( + Bootstrapper* bootstrapper, + const char* source, + size_t length) + : data_(source), length_(length) { + if (bootstrapper->delete_these_non_arrays_on_tear_down_ == NULL) { + bootstrapper->delete_these_non_arrays_on_tear_down_ = new List<char*>(2); } // The resources are small objects and we only make a fixed number of // them, but let's clean them up on exit for neatness. - delete_these_non_arrays_on_tear_down-> + bootstrapper->delete_these_non_arrays_on_tear_down_-> Add(reinterpret_cast<char*>(this)); } +Bootstrapper::Bootstrapper() + : nesting_(0), + extensions_cache_(Script::TYPE_EXTENSION), + delete_these_non_arrays_on_tear_down_(NULL), + delete_these_arrays_on_tear_down_(NULL) { +} + + Handle<String> Bootstrapper::NativesSourceLookup(int index) { ASSERT(0 <= index && index < Natives::GetBuiltinsCount()); - if (Heap::natives_source_cache()->get(index)->IsUndefined()) { + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + Heap* heap = isolate->heap(); + if (heap->natives_source_cache()->get(index)->IsUndefined()) { if (!Snapshot::IsEnabled() || FLAG_new_snapshot) { // We can use external strings for the natives. + Vector<const char> source = Natives::GetRawScriptSource(index); NativesExternalStringResource* resource = - new NativesExternalStringResource( - Natives::GetScriptSource(index).start()); + new NativesExternalStringResource(this, + source.start(), + source.length()); Handle<String> source_code = - Factory::NewExternalStringFromAscii(resource); - Heap::natives_source_cache()->set(index, *source_code); + factory->NewExternalStringFromAscii(resource); + heap->natives_source_cache()->set(index, *source_code); } else { // Old snapshot code can't cope with external strings at all. Handle<String> source_code = - Factory::NewStringFromAscii(Natives::GetScriptSource(index)); - Heap::natives_source_cache()->set(index, *source_code); + factory->NewStringFromAscii(Natives::GetRawScriptSource(index)); + heap->natives_source_cache()->set(index, *source_code); } } - Handle<Object> cached_source(Heap::natives_source_cache()->get(index)); + Handle<Object> cached_source(heap->natives_source_cache()->get(index)); return Handle<String>::cast(cached_source); } void Bootstrapper::Initialize(bool create_heap_objects) { - extensions_cache.Initialize(create_heap_objects); + extensions_cache_.Initialize(create_heap_objects); GCExtension::Register(); ExternalizeStringExtension::Register(); } @@ -146,45 +106,46 @@ void Bootstrapper::Initialize(bool create_heap_objects) { char* Bootstrapper::AllocateAutoDeletedArray(int bytes) { char* memory = new char[bytes]; if (memory != NULL) { - if (delete_these_arrays_on_tear_down == NULL) { - delete_these_arrays_on_tear_down = new List<char*>(2); + if (delete_these_arrays_on_tear_down_ == NULL) { + delete_these_arrays_on_tear_down_ = new List<char*>(2); } - delete_these_arrays_on_tear_down->Add(memory); + delete_these_arrays_on_tear_down_->Add(memory); } return memory; } void Bootstrapper::TearDown() { - if (delete_these_non_arrays_on_tear_down != NULL) { - int len = delete_these_non_arrays_on_tear_down->length(); + if (delete_these_non_arrays_on_tear_down_ != NULL) { + int len = delete_these_non_arrays_on_tear_down_->length(); ASSERT(len < 20); // Don't use this mechanism for unbounded allocations. for (int i = 0; i < len; i++) { - delete delete_these_non_arrays_on_tear_down->at(i); - delete_these_non_arrays_on_tear_down->at(i) = NULL; + delete delete_these_non_arrays_on_tear_down_->at(i); + delete_these_non_arrays_on_tear_down_->at(i) = NULL; } - delete delete_these_non_arrays_on_tear_down; - delete_these_non_arrays_on_tear_down = NULL; + delete delete_these_non_arrays_on_tear_down_; + delete_these_non_arrays_on_tear_down_ = NULL; } - if (delete_these_arrays_on_tear_down != NULL) { - int len = delete_these_arrays_on_tear_down->length(); + if (delete_these_arrays_on_tear_down_ != NULL) { + int len = delete_these_arrays_on_tear_down_->length(); ASSERT(len < 1000); // Don't use this mechanism for unbounded allocations. for (int i = 0; i < len; i++) { - delete[] delete_these_arrays_on_tear_down->at(i); - delete_these_arrays_on_tear_down->at(i) = NULL; + delete[] delete_these_arrays_on_tear_down_->at(i); + delete_these_arrays_on_tear_down_->at(i) = NULL; } - delete delete_these_arrays_on_tear_down; - delete_these_arrays_on_tear_down = NULL; + delete delete_these_arrays_on_tear_down_; + delete_these_arrays_on_tear_down_ = NULL; } - extensions_cache.Initialize(false); // Yes, symmetrical + extensions_cache_.Initialize(false); // Yes, symmetrical } class Genesis BASE_EMBEDDED { public: - Genesis(Handle<Object> global_object, + Genesis(Isolate* isolate, + Handle<Object> global_object, v8::Handle<v8::ObjectTemplate> global_template, v8::ExtensionConfiguration* extensions); ~Genesis() { } @@ -193,8 +154,13 @@ class Genesis BASE_EMBEDDED { Genesis* previous() { return previous_; } + Isolate* isolate() const { return isolate_; } + Factory* factory() const { return isolate_->factory(); } + Heap* heap() const { return isolate_->heap(); } + private: Handle<Context> global_context_; + Isolate* isolate_; // There may be more than one active genesis object: When GC is // triggered during environment creation there may be weak handle @@ -206,7 +172,11 @@ class Genesis BASE_EMBEDDED { // Creates some basic objects. Used for creating a context from scratch. void CreateRoots(); // Creates the empty function. Used for creating a context from scratch. - Handle<JSFunction> CreateEmptyFunction(); + Handle<JSFunction> CreateEmptyFunction(Isolate* isolate); + // Creates the ThrowTypeError function. ECMA 5th Ed. 13.2.3 + Handle<JSFunction> GetThrowTypeErrorFunction(); + + void CreateStrictModeFunctionMaps(Handle<JSFunction> empty); // Creates the global objects using the global and the template passed in // through the API. We call this regardless of whether we are building a // context from scratch or using a deserialized one from the partial snapshot @@ -232,7 +202,9 @@ class Genesis BASE_EMBEDDED { // Installs the contents of the native .js files on the global objects. // Used for creating a context from scratch. void InstallNativeFunctions(); + void InstallExperimentalNativeFunctions(); bool InstallNatives(); + bool InstallExperimentalNatives(); void InstallBuiltinFunctionIds(); void InstallJSFunctionResultCaches(); void InitializeNormalizedMapCaches(); @@ -260,11 +232,26 @@ class Genesis BASE_EMBEDDED { ADD_READONLY_PROTOTYPE, ADD_WRITEABLE_PROTOTYPE }; + + Handle<Map> CreateFunctionMap(PrototypePropertyMode prototype_mode); + Handle<DescriptorArray> ComputeFunctionInstanceDescriptor( PrototypePropertyMode prototypeMode); void MakeFunctionInstancePrototypeWritable(); - static bool CompileBuiltin(int index); + Handle<Map> CreateStrictModeFunctionMap( + PrototypePropertyMode prototype_mode, + Handle<JSFunction> empty_function, + Handle<FixedArray> arguments_callbacks, + Handle<FixedArray> caller_callbacks); + + Handle<DescriptorArray> ComputeStrictFunctionInstanceDescriptor( + PrototypePropertyMode propertyMode, + Handle<FixedArray> arguments, + Handle<FixedArray> caller); + + static bool CompileBuiltin(Isolate* isolate, int index); + static bool CompileExperimentalBuiltin(Isolate* isolate, int index); static bool CompileNative(Vector<const char> name, Handle<String> source); static bool CompileScriptCached(Vector<const char> name, Handle<String> source, @@ -274,25 +261,34 @@ class Genesis BASE_EMBEDDED { bool use_runtime_context); Handle<Context> result_; - Handle<JSFunction> empty_function_; + + // Function instance maps. Function literal maps are created initially with + // a read only prototype for the processing of JS builtins. Later the function + // instance maps are replaced in order to make prototype writable. + // These are the final, writable prototype, maps. + Handle<Map> function_instance_map_writable_prototype_; + Handle<Map> strict_mode_function_instance_map_writable_prototype_; + Handle<JSFunction> throw_type_error_function; + BootstrapperActive active_; friend class Bootstrapper; }; void Bootstrapper::Iterate(ObjectVisitor* v) { - extensions_cache.Iterate(v); + extensions_cache_.Iterate(v); v->Synchronize("Extensions"); } Handle<Context> Bootstrapper::CreateEnvironment( + Isolate* isolate, Handle<Object> global_object, v8::Handle<v8::ObjectTemplate> global_template, v8::ExtensionConfiguration* extensions) { HandleScope scope; Handle<Context> env; - Genesis genesis(global_object, global_template, extensions); + Genesis genesis(isolate, global_object, global_template, extensions); env = genesis.result(); if (!env.is_null()) { if (InstallExtensions(env, extensions)) { @@ -305,17 +301,19 @@ Handle<Context> Bootstrapper::CreateEnvironment( static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) { // object.__proto__ = proto; + Factory* factory = object->GetIsolate()->factory(); Handle<Map> old_to_map = Handle<Map>(object->map()); - Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map); + Handle<Map> new_to_map = factory->CopyMapDropTransitions(old_to_map); new_to_map->set_prototype(*proto); object->set_map(*new_to_map); } void Bootstrapper::DetachGlobal(Handle<Context> env) { - JSGlobalProxy::cast(env->global_proxy())->set_context(*Factory::null_value()); + Factory* factory = env->GetIsolate()->factory(); + JSGlobalProxy::cast(env->global_proxy())->set_context(*factory->null_value()); SetObjectPrototype(Handle<JSObject>(env->global_proxy()), - Factory::null_value()); + factory->null_value()); env->set_global_proxy(env->global()); env->global()->set_global_receiver(env->global()); } @@ -339,11 +337,13 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target, Handle<JSObject> prototype, Builtins::Name call, bool is_ecma_native) { - Handle<String> symbol = Factory::LookupAsciiSymbol(name); - Handle<Code> call_code = Handle<Code>(Builtins::builtin(call)); + Isolate* isolate = target->GetIsolate(); + Factory* factory = isolate->factory(); + Handle<String> symbol = factory->LookupAsciiSymbol(name); + Handle<Code> call_code = Handle<Code>(isolate->builtins()->builtin(call)); Handle<JSFunction> function = prototype.is_null() ? - Factory::NewFunctionWithoutPrototype(symbol, call_code) : - Factory::NewFunctionWithPrototype(symbol, + factory->NewFunctionWithoutPrototype(symbol, call_code) : + factory->NewFunctionWithPrototype(symbol, type, instance_size, prototype, @@ -359,161 +359,300 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target, Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor( PrototypePropertyMode prototypeMode) { - Handle<DescriptorArray> result = Factory::empty_descriptor_array(); + Handle<DescriptorArray> descriptors = + factory()->NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE + ? 4 + : 5); + PropertyAttributes attributes = + static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); + { // Add length. + Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength); + CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes); + descriptors->Set(0, &d); + } + { // Add name. + Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName); + CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes); + descriptors->Set(1, &d); + } + { // Add arguments. + Handle<Foreign> foreign = + factory()->NewForeign(&Accessors::FunctionArguments); + CallbacksDescriptor d(*factory()->arguments_symbol(), *foreign, attributes); + descriptors->Set(2, &d); + } + { // Add caller. + Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionCaller); + CallbacksDescriptor d(*factory()->caller_symbol(), *foreign, attributes); + descriptors->Set(3, &d); + } if (prototypeMode != DONT_ADD_PROTOTYPE) { - PropertyAttributes attributes = static_cast<PropertyAttributes>( - DONT_ENUM | - DONT_DELETE | - (prototypeMode == ADD_READONLY_PROTOTYPE ? READ_ONLY : 0)); - result = - Factory::CopyAppendProxyDescriptor( - result, - Factory::prototype_symbol(), - Factory::NewProxy(&Accessors::FunctionPrototype), - attributes); + // Add prototype. + if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) { + attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY); + } + Handle<Foreign> foreign = + factory()->NewForeign(&Accessors::FunctionPrototype); + CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes); + descriptors->Set(4, &d); } + descriptors->Sort(); + return descriptors; +} - PropertyAttributes attributes = - static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); - // Add length. - result = - Factory::CopyAppendProxyDescriptor( - result, - Factory::length_symbol(), - Factory::NewProxy(&Accessors::FunctionLength), - attributes); - - // Add name. - result = - Factory::CopyAppendProxyDescriptor( - result, - Factory::name_symbol(), - Factory::NewProxy(&Accessors::FunctionName), - attributes); - - // Add arguments. - result = - Factory::CopyAppendProxyDescriptor( - result, - Factory::arguments_symbol(), - Factory::NewProxy(&Accessors::FunctionArguments), - attributes); - - // Add caller. - result = - Factory::CopyAppendProxyDescriptor( - result, - Factory::caller_symbol(), - Factory::NewProxy(&Accessors::FunctionCaller), - attributes); - return result; +Handle<Map> Genesis::CreateFunctionMap(PrototypePropertyMode prototype_mode) { + Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); + Handle<DescriptorArray> descriptors = + ComputeFunctionInstanceDescriptor(prototype_mode); + map->set_instance_descriptors(*descriptors); + map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE); + return map; } -Handle<JSFunction> Genesis::CreateEmptyFunction() { - // Allocate the map for function instances. - Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); - global_context()->set_function_instance_map(*fm); +Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { + // Allocate the map for function instances. Maps are allocated first and their + // prototypes patched later, once empty function is created. + // Please note that the prototype property for function instances must be // writable. - Handle<DescriptorArray> function_map_descriptors = - ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE); - fm->set_instance_descriptors(*function_map_descriptors); - fm->set_function_with_prototype(true); + Handle<Map> function_instance_map = + CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE); + global_context()->set_function_instance_map(*function_instance_map); // Functions with this map will not have a 'prototype' property, and // can not be used as constructors. Handle<Map> function_without_prototype_map = - Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); + CreateFunctionMap(DONT_ADD_PROTOTYPE); global_context()->set_function_without_prototype_map( *function_without_prototype_map); - Handle<DescriptorArray> function_without_prototype_map_descriptors = - ComputeFunctionInstanceDescriptor(DONT_ADD_PROTOTYPE); - function_without_prototype_map->set_instance_descriptors( - *function_without_prototype_map_descriptors); - function_without_prototype_map->set_function_with_prototype(false); - // Allocate the function map first and then patch the prototype later - fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); - global_context()->set_function_map(*fm); - function_map_descriptors = - ComputeFunctionInstanceDescriptor(ADD_READONLY_PROTOTYPE); - fm->set_instance_descriptors(*function_map_descriptors); - fm->set_function_with_prototype(true); + // Allocate the function map. This map is temporary, used only for processing + // of builtins. + // Later the map is replaced with writable prototype map, allocated below. + Handle<Map> function_map = CreateFunctionMap(ADD_READONLY_PROTOTYPE); + global_context()->set_function_map(*function_map); - Handle<String> object_name = Handle<String>(Heap::Object_symbol()); + // The final map for functions. Writeable prototype. + // This map is installed in MakeFunctionInstancePrototypeWritable. + function_instance_map_writable_prototype_ = + CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE); + + Factory* factory = isolate->factory(); + Heap* heap = isolate->heap(); + + Handle<String> object_name = Handle<String>(heap->Object_symbol()); { // --- O b j e c t --- Handle<JSFunction> object_fun = - Factory::NewFunction(object_name, Factory::null_value()); + factory->NewFunction(object_name, factory->null_value()); Handle<Map> object_function_map = - Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); object_fun->set_initial_map(*object_function_map); object_function_map->set_constructor(*object_fun); global_context()->set_object_function(*object_fun); // Allocate a new prototype for the object function. - Handle<JSObject> prototype = Factory::NewJSObject(Top::object_function(), - TENURED); + Handle<JSObject> prototype = factory->NewJSObject( + isolate->object_function(), + TENURED); global_context()->set_initial_object_prototype(*prototype); SetPrototype(object_fun, prototype); object_function_map-> - set_instance_descriptors(Heap::empty_descriptor_array()); + set_instance_descriptors(heap->empty_descriptor_array()); } // Allocate the empty function as the prototype for function ECMAScript // 262 15.3.4. - Handle<String> symbol = Factory::LookupAsciiSymbol("Empty"); + Handle<String> symbol = factory->LookupAsciiSymbol("Empty"); Handle<JSFunction> empty_function = - Factory::NewFunctionWithoutPrototype(symbol); + factory->NewFunctionWithoutPrototype(symbol, kNonStrictMode); // --- E m p t y --- Handle<Code> code = - Handle<Code>(Builtins::builtin(Builtins::EmptyFunction)); + Handle<Code>(isolate->builtins()->builtin( + Builtins::kEmptyFunction)); empty_function->set_code(*code); empty_function->shared()->set_code(*code); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}")); - Handle<Script> script = Factory::NewScript(source); + Handle<String> source = factory->NewStringFromAscii(CStrVector("() {}")); + Handle<Script> script = factory->NewScript(source); script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); empty_function->shared()->set_script(*script); empty_function->shared()->set_start_position(0); empty_function->shared()->set_end_position(source->length()); empty_function->shared()->DontAdaptArguments(); + + // Set prototypes for the function maps. global_context()->function_map()->set_prototype(*empty_function); global_context()->function_instance_map()->set_prototype(*empty_function); global_context()->function_without_prototype_map()-> set_prototype(*empty_function); + function_instance_map_writable_prototype_->set_prototype(*empty_function); // Allocate the function map first and then patch the prototype later - Handle<Map> empty_fm = Factory::CopyMapDropDescriptors( + Handle<Map> empty_fm = factory->CopyMapDropDescriptors( function_without_prototype_map); empty_fm->set_instance_descriptors( - *function_without_prototype_map_descriptors); + function_without_prototype_map->instance_descriptors()); empty_fm->set_prototype(global_context()->object_function()->prototype()); empty_function->set_map(*empty_fm); return empty_function; } +Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor( + PrototypePropertyMode prototypeMode, + Handle<FixedArray> arguments, + Handle<FixedArray> caller) { + Handle<DescriptorArray> descriptors = + factory()->NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE + ? 4 + : 5); + PropertyAttributes attributes = static_cast<PropertyAttributes>( + DONT_ENUM | DONT_DELETE | READ_ONLY); + + { // length + Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength); + CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes); + descriptors->Set(0, &d); + } + { // name + Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName); + CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes); + descriptors->Set(1, &d); + } + { // arguments + CallbacksDescriptor d(*factory()->arguments_symbol(), + *arguments, + attributes); + descriptors->Set(2, &d); + } + { // caller + CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attributes); + descriptors->Set(3, &d); + } + + // prototype + if (prototypeMode != DONT_ADD_PROTOTYPE) { + if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) { + attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY); + } + Handle<Foreign> foreign = + factory()->NewForeign(&Accessors::FunctionPrototype); + CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes); + descriptors->Set(4, &d); + } + + descriptors->Sort(); + return descriptors; +} + + +// ECMAScript 5th Edition, 13.2.3 +Handle<JSFunction> Genesis::GetThrowTypeErrorFunction() { + if (throw_type_error_function.is_null()) { + Handle<String> name = factory()->LookupAsciiSymbol("ThrowTypeError"); + throw_type_error_function = + factory()->NewFunctionWithoutPrototype(name, kNonStrictMode); + Handle<Code> code(isolate()->builtins()->builtin( + Builtins::kStrictModePoisonPill)); + throw_type_error_function->set_map( + global_context()->function_map()); + throw_type_error_function->set_code(*code); + throw_type_error_function->shared()->set_code(*code); + throw_type_error_function->shared()->DontAdaptArguments(); + + PreventExtensions(throw_type_error_function); + } + return throw_type_error_function; +} + + +Handle<Map> Genesis::CreateStrictModeFunctionMap( + PrototypePropertyMode prototype_mode, + Handle<JSFunction> empty_function, + Handle<FixedArray> arguments_callbacks, + Handle<FixedArray> caller_callbacks) { + Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); + Handle<DescriptorArray> descriptors = + ComputeStrictFunctionInstanceDescriptor(prototype_mode, + arguments_callbacks, + caller_callbacks); + map->set_instance_descriptors(*descriptors); + map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE); + map->set_prototype(*empty_function); + return map; +} + + +void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) { + // Create the callbacks arrays for ThrowTypeError functions. + // The get/set callacks are filled in after the maps are created below. + Factory* factory = empty->GetIsolate()->factory(); + Handle<FixedArray> arguments = factory->NewFixedArray(2, TENURED); + Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED); + + // Allocate map for the strict mode function instances. + Handle<Map> strict_mode_function_instance_map = + CreateStrictModeFunctionMap( + ADD_WRITEABLE_PROTOTYPE, empty, arguments, caller); + global_context()->set_strict_mode_function_instance_map( + *strict_mode_function_instance_map); + + // Allocate map for the prototype-less strict mode instances. + Handle<Map> strict_mode_function_without_prototype_map = + CreateStrictModeFunctionMap( + DONT_ADD_PROTOTYPE, empty, arguments, caller); + global_context()->set_strict_mode_function_without_prototype_map( + *strict_mode_function_without_prototype_map); + + // Allocate map for the strict mode functions. This map is temporary, used + // only for processing of builtins. + // Later the map is replaced with writable prototype map, allocated below. + Handle<Map> strict_mode_function_map = + CreateStrictModeFunctionMap( + ADD_READONLY_PROTOTYPE, empty, arguments, caller); + global_context()->set_strict_mode_function_map( + *strict_mode_function_map); + + // The final map for the strict mode functions. Writeable prototype. + // This map is installed in MakeFunctionInstancePrototypeWritable. + strict_mode_function_instance_map_writable_prototype_ = + CreateStrictModeFunctionMap( + ADD_WRITEABLE_PROTOTYPE, empty, arguments, caller); + + // Create the ThrowTypeError function instance. + Handle<JSFunction> throw_function = + GetThrowTypeErrorFunction(); + + // Complete the callback fixed arrays. + arguments->set(0, *throw_function); + arguments->set(1, *throw_function); + caller->set(0, *throw_function); + caller->set(1, *throw_function); +} + + static void AddToWeakGlobalContextList(Context* context) { ASSERT(context->IsGlobalContext()); + Heap* heap = context->GetIsolate()->heap(); #ifdef DEBUG { // NOLINT ASSERT(context->get(Context::NEXT_CONTEXT_LINK)->IsUndefined()); // Check that context is not in the list yet. - for (Object* current = Heap::global_contexts_list(); + for (Object* current = heap->global_contexts_list(); !current->IsUndefined(); current = Context::cast(current)->get(Context::NEXT_CONTEXT_LINK)) { ASSERT(current != context); } } #endif - context->set(Context::NEXT_CONTEXT_LINK, Heap::global_contexts_list()); - Heap::set_global_contexts_list(context); + context->set(Context::NEXT_CONTEXT_LINK, heap->global_contexts_list()); + heap->set_global_contexts_list(context); } @@ -522,11 +661,10 @@ void Genesis::CreateRoots() { // closure and extension object later (we need the empty function // and the global object, but in order to create those, we need the // global context). - global_context_ = - Handle<Context>::cast( - GlobalHandles::Create(*Factory::NewGlobalContext())); + global_context_ = Handle<Context>::cast(isolate()->global_handles()->Create( + *factory()->NewGlobalContext())); AddToWeakGlobalContextList(*global_context_); - Top::set_context(*global_context()); + isolate()->set_context(*global_context()); // Allocate the message listeners object. { @@ -570,29 +708,33 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals( } if (js_global_template.is_null()) { - Handle<String> name = Handle<String>(Heap::empty_symbol()); - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal)); + Handle<String> name = Handle<String>(heap()->empty_symbol()); + Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin( + Builtins::kIllegal)); js_global_function = - Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE, - JSGlobalObject::kSize, code, true); + factory()->NewFunction(name, JS_GLOBAL_OBJECT_TYPE, + JSGlobalObject::kSize, code, true); // Change the constructor property of the prototype of the // hidden global function to refer to the Object function. Handle<JSObject> prototype = Handle<JSObject>( JSObject::cast(js_global_function->instance_prototype())); SetLocalPropertyNoThrow( - prototype, Factory::constructor_symbol(), Top::object_function(), NONE); + prototype, + factory()->constructor_symbol(), + isolate()->object_function(), + NONE); } else { Handle<FunctionTemplateInfo> js_global_constructor( FunctionTemplateInfo::cast(js_global_template->constructor())); js_global_function = - Factory::CreateApiFunction(js_global_constructor, - Factory::InnerGlobalObject); + factory()->CreateApiFunction(js_global_constructor, + factory()->InnerGlobalObject); } js_global_function->initial_map()->set_is_hidden_prototype(); Handle<GlobalObject> inner_global = - Factory::NewGlobalObject(js_global_function); + factory()->NewGlobalObject(js_global_function); if (inner_global_out != NULL) { *inner_global_out = inner_global; } @@ -600,22 +742,23 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals( // Step 2: create or re-initialize the global proxy object. Handle<JSFunction> global_proxy_function; if (global_template.IsEmpty()) { - Handle<String> name = Handle<String>(Heap::empty_symbol()); - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal)); + Handle<String> name = Handle<String>(heap()->empty_symbol()); + Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin( + Builtins::kIllegal)); global_proxy_function = - Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE, - JSGlobalProxy::kSize, code, true); + factory()->NewFunction(name, JS_GLOBAL_PROXY_TYPE, + JSGlobalProxy::kSize, code, true); } else { Handle<ObjectTemplateInfo> data = v8::Utils::OpenHandle(*global_template); Handle<FunctionTemplateInfo> global_constructor( FunctionTemplateInfo::cast(data->constructor())); global_proxy_function = - Factory::CreateApiFunction(global_constructor, - Factory::OuterGlobalObject); + factory()->CreateApiFunction(global_constructor, + factory()->OuterGlobalObject); } - Handle<String> global_name = Factory::LookupAsciiSymbol("global"); + Handle<String> global_name = factory()->LookupAsciiSymbol("global"); global_proxy_function->shared()->set_instance_class_name(*global_name); global_proxy_function->initial_map()->set_is_access_check_needed(true); @@ -629,7 +772,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals( Handle<JSGlobalProxy>::cast(global_object)); } else { return Handle<JSGlobalProxy>::cast( - Factory::NewJSObject(global_proxy_function, TENURED)); + factory()->NewJSObject(global_proxy_function, TENURED)); } } @@ -654,7 +797,7 @@ void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) { static const PropertyAttributes attributes = static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); ForceSetProperty(builtins_global, - Factory::LookupAsciiSymbol("global"), + factory()->LookupAsciiSymbol("global"), inner_global, attributes); // Setup the reference from the global object to the builtins object. @@ -671,7 +814,6 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, // --- G l o b a l C o n t e x t --- // Use the empty function as closure (no scope info). global_context()->set_closure(*empty_function); - global_context()->set_fcontext(*global_context()); global_context()->set_previous(NULL); // Set extension and global object. global_context()->set_extension(*inner_global); @@ -682,33 +824,37 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, // object reinitialization. global_context()->set_security_token(*inner_global); - Handle<String> object_name = Handle<String>(Heap::Object_symbol()); + Isolate* isolate = inner_global->GetIsolate(); + Factory* factory = isolate->factory(); + Heap* heap = isolate->heap(); + + Handle<String> object_name = Handle<String>(heap->Object_symbol()); SetLocalPropertyNoThrow(inner_global, object_name, - Top::object_function(), DONT_ENUM); + isolate->object_function(), DONT_ENUM); Handle<JSObject> global = Handle<JSObject>(global_context()->global()); // Install global Function object InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize, - empty_function, Builtins::Illegal, true); // ECMA native. + empty_function, Builtins::kIllegal, true); // ECMA native. { // --- A r r a y --- Handle<JSFunction> array_function = InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize, - Top::initial_object_prototype(), Builtins::ArrayCode, - true); + isolate->initial_object_prototype(), + Builtins::kArrayCode, true); array_function->shared()->set_construct_stub( - Builtins::builtin(Builtins::ArrayConstructCode)); + isolate->builtins()->builtin(Builtins::kArrayConstructCode)); array_function->shared()->DontAdaptArguments(); // This seems a bit hackish, but we need to make sure Array.length // is 1. array_function->shared()->set_length(1); Handle<DescriptorArray> array_descriptors = - Factory::CopyAppendProxyDescriptor( - Factory::empty_descriptor_array(), - Factory::length_symbol(), - Factory::NewProxy(&Accessors::ArrayLength), + factory->CopyAppendForeignDescriptor( + factory->empty_descriptor_array(), + factory->length_symbol(), + factory->NewForeign(&Accessors::ArrayLength), static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE)); // Cache the fast JavaScript array map @@ -725,33 +871,33 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, { // --- N u m b e r --- Handle<JSFunction> number_fun = InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize, - Top::initial_object_prototype(), Builtins::Illegal, - true); + isolate->initial_object_prototype(), + Builtins::kIllegal, true); global_context()->set_number_function(*number_fun); } { // --- B o o l e a n --- Handle<JSFunction> boolean_fun = InstallFunction(global, "Boolean", JS_VALUE_TYPE, JSValue::kSize, - Top::initial_object_prototype(), Builtins::Illegal, - true); + isolate->initial_object_prototype(), + Builtins::kIllegal, true); global_context()->set_boolean_function(*boolean_fun); } { // --- S t r i n g --- Handle<JSFunction> string_fun = InstallFunction(global, "String", JS_VALUE_TYPE, JSValue::kSize, - Top::initial_object_prototype(), Builtins::Illegal, - true); + isolate->initial_object_prototype(), + Builtins::kIllegal, true); string_fun->shared()->set_construct_stub( - Builtins::builtin(Builtins::StringConstructCode)); + isolate->builtins()->builtin(Builtins::kStringConstructCode)); global_context()->set_string_function(*string_fun); // Add 'length' property to strings. Handle<DescriptorArray> string_descriptors = - Factory::CopyAppendProxyDescriptor( - Factory::empty_descriptor_array(), - Factory::length_symbol(), - Factory::NewProxy(&Accessors::StringLength), + factory->CopyAppendForeignDescriptor( + factory->empty_descriptor_array(), + factory->length_symbol(), + factory->NewForeign(&Accessors::StringLength), static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY)); @@ -765,8 +911,8 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, // Builtin functions for Date.prototype. Handle<JSFunction> date_fun = InstallFunction(global, "Date", JS_VALUE_TYPE, JSValue::kSize, - Top::initial_object_prototype(), Builtins::Illegal, - true); + isolate->initial_object_prototype(), + Builtins::kIllegal, true); global_context()->set_date_function(*date_fun); } @@ -776,8 +922,8 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, // Builtin functions for RegExp.prototype. Handle<JSFunction> regexp_fun = InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize, - Top::initial_object_prototype(), Builtins::Illegal, - true); + isolate->initial_object_prototype(), + Builtins::kIllegal, true); global_context()->set_regexp_function(*regexp_fun); ASSERT(regexp_fun->has_initial_map()); @@ -785,13 +931,13 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ASSERT_EQ(0, initial_map->inobject_properties()); - Handle<DescriptorArray> descriptors = Factory::NewDescriptorArray(5); + Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(5); PropertyAttributes final = static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); int enum_index = 0; { // ECMA-262, section 15.10.7.1. - FieldDescriptor field(Heap::source_symbol(), + FieldDescriptor field(heap->source_symbol(), JSRegExp::kSourceFieldIndex, final, enum_index++); @@ -799,7 +945,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, } { // ECMA-262, section 15.10.7.2. - FieldDescriptor field(Heap::global_symbol(), + FieldDescriptor field(heap->global_symbol(), JSRegExp::kGlobalFieldIndex, final, enum_index++); @@ -807,7 +953,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, } { // ECMA-262, section 15.10.7.3. - FieldDescriptor field(Heap::ignore_case_symbol(), + FieldDescriptor field(heap->ignore_case_symbol(), JSRegExp::kIgnoreCaseFieldIndex, final, enum_index++); @@ -815,7 +961,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, } { // ECMA-262, section 15.10.7.4. - FieldDescriptor field(Heap::multiline_symbol(), + FieldDescriptor field(heap->multiline_symbol(), JSRegExp::kMultilineFieldIndex, final, enum_index++); @@ -825,7 +971,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, // ECMA-262, section 15.10.7.5. PropertyAttributes writable = static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); - FieldDescriptor field(Heap::last_index_symbol(), + FieldDescriptor field(heap->last_index_symbol(), JSRegExp::kLastIndexFieldIndex, writable, enum_index++); @@ -844,13 +990,13 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, } { // -- J S O N - Handle<String> name = Factory::NewStringFromAscii(CStrVector("JSON")); - Handle<JSFunction> cons = Factory::NewFunction( + Handle<String> name = factory->NewStringFromAscii(CStrVector("JSON")); + Handle<JSFunction> cons = factory->NewFunction( name, - Factory::the_hole_value()); + factory->the_hole_value()); cons->SetInstancePrototype(global_context()->initial_object_prototype()); cons->SetInstanceClassName(*name); - Handle<JSObject> json_object = Factory::NewJSObject(cons, TENURED); + Handle<JSObject> json_object = factory->NewJSObject(cons, TENURED); ASSERT(json_object->IsJSObject()); SetLocalPropertyNoThrow(global, name, json_object, DONT_ENUM); global_context()->set_json_object(*json_object); @@ -860,14 +1006,15 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, // Make sure we can recognize argument objects at runtime. // This is done by introducing an anonymous function with // class_name equals 'Arguments'. - Handle<String> symbol = Factory::LookupAsciiSymbol("Arguments"); - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal)); + Handle<String> symbol = factory->LookupAsciiSymbol("Arguments"); + Handle<Code> code = Handle<Code>( + isolate->builtins()->builtin(Builtins::kIllegal)); Handle<JSObject> prototype = Handle<JSObject>( JSObject::cast(global_context()->object_function()->prototype())); Handle<JSFunction> function = - Factory::NewFunctionWithPrototype(symbol, + factory->NewFunctionWithPrototype(symbol, JS_OBJECT_TYPE, JSObject::kHeaderSize, prototype, @@ -876,30 +1023,117 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ASSERT(!function->has_initial_map()); function->shared()->set_instance_class_name(*symbol); function->shared()->set_expected_nof_properties(2); - Handle<JSObject> result = Factory::NewJSObject(function); + Handle<JSObject> result = factory->NewJSObject(function); global_context()->set_arguments_boilerplate(*result); - // Note: callee must be added as the first property and - // length must be added as the second property. - SetLocalPropertyNoThrow(result, Factory::callee_symbol(), - Factory::undefined_value(), + // Note: length must be added as the first property and + // callee must be added as the second property. + SetLocalPropertyNoThrow(result, factory->length_symbol(), + factory->undefined_value(), DONT_ENUM); - SetLocalPropertyNoThrow(result, Factory::length_symbol(), - Factory::undefined_value(), + SetLocalPropertyNoThrow(result, factory->callee_symbol(), + factory->undefined_value(), DONT_ENUM); #ifdef DEBUG LookupResult lookup; - result->LocalLookup(Heap::callee_symbol(), &lookup); + result->LocalLookup(heap->callee_symbol(), &lookup); + ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); + ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex); + + result->LocalLookup(heap->length_symbol(), &lookup); ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); - ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index); + ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex); + + ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex); + ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex); + + // Check the state of the object. + ASSERT(result->HasFastProperties()); + ASSERT(result->HasFastElements()); +#endif + } + + { // --- aliased_arguments_boilerplate_ + Handle<Map> old_map(global_context()->arguments_boilerplate()->map()); + Handle<Map> new_map = factory->CopyMapDropTransitions(old_map); + new_map->set_pre_allocated_property_fields(2); + Handle<JSObject> result = factory->NewJSObjectFromMap(new_map); + new_map->set_elements_kind(JSObject::NON_STRICT_ARGUMENTS_ELEMENTS); + // Set up a well-formed parameter map to make assertions happy. + Handle<FixedArray> elements = factory->NewFixedArray(2); + elements->set_map(heap->non_strict_arguments_elements_map()); + Handle<FixedArray> array; + array = factory->NewFixedArray(0); + elements->set(0, *array); + array = factory->NewFixedArray(0); + elements->set(1, *array); + result->set_elements(*elements); + global_context()->set_aliased_arguments_boilerplate(*result); + } + + { // --- strict mode arguments boilerplate + const PropertyAttributes attributes = + static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); + + // Create the ThrowTypeError functions. + Handle<FixedArray> callee = factory->NewFixedArray(2, TENURED); + Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED); + + Handle<JSFunction> throw_function = + GetThrowTypeErrorFunction(); + + // Install the ThrowTypeError functions. + callee->set(0, *throw_function); + callee->set(1, *throw_function); + caller->set(0, *throw_function); + caller->set(1, *throw_function); + + // Create the descriptor array for the arguments object. + Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3); + { // length + FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM); + descriptors->Set(0, &d); + } + { // callee + CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes); + descriptors->Set(1, &d); + } + { // caller + CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes); + descriptors->Set(2, &d); + } + descriptors->Sort(); + + // Create the map. Allocate one in-object field for length. + Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, + Heap::kArgumentsObjectSizeStrict); + map->set_instance_descriptors(*descriptors); + map->set_function_with_prototype(true); + map->set_prototype(global_context()->object_function()->prototype()); + map->set_pre_allocated_property_fields(1); + map->set_inobject_properties(1); + + // Copy constructor from the non-strict arguments boilerplate. + map->set_constructor( + global_context()->arguments_boilerplate()->map()->constructor()); + + // Allocate the arguments boilerplate object. + Handle<JSObject> result = factory->NewJSObjectFromMap(map); + global_context()->set_strict_mode_arguments_boilerplate(*result); + + // Add length property only for strict mode boilerplate. + SetLocalPropertyNoThrow(result, factory->length_symbol(), + factory->undefined_value(), + DONT_ENUM); - result->LocalLookup(Heap::length_symbol(), &lookup); +#ifdef DEBUG + LookupResult lookup; + result->LocalLookup(heap->length_symbol(), &lookup); ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); - ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index); + ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex); - ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index); - ASSERT(result->map()->inobject_properties() > Heap::arguments_length_index); + ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex); // Check the state of the object. ASSERT(result->HasFastProperties()); @@ -909,15 +1143,16 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, { // --- context extension // Create a function for the context extension objects. - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal)); + Handle<Code> code = Handle<Code>( + isolate->builtins()->builtin(Builtins::kIllegal)); Handle<JSFunction> context_extension_fun = - Factory::NewFunction(Factory::empty_symbol(), + factory->NewFunction(factory->empty_symbol(), JS_CONTEXT_EXTENSION_OBJECT_TYPE, JSObject::kHeaderSize, code, true); - Handle<String> name = Factory::LookupAsciiSymbol("context_extension"); + Handle<String> name = factory->LookupAsciiSymbol("context_extension"); context_extension_fun->shared()->set_instance_class_name(*name); global_context()->set_context_extension_function(*context_extension_fun); } @@ -926,9 +1161,10 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, { // Setup the call-as-function delegate. Handle<Code> code = - Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction)); + Handle<Code>(isolate->builtins()->builtin( + Builtins::kHandleApiCallAsFunction)); Handle<JSFunction> delegate = - Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE, + factory->NewFunction(factory->empty_symbol(), JS_OBJECT_TYPE, JSObject::kHeaderSize, code, true); global_context()->set_call_as_function_delegate(*delegate); delegate->shared()->DontAdaptArguments(); @@ -937,44 +1173,57 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, { // Setup the call-as-constructor delegate. Handle<Code> code = - Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsConstructor)); + Handle<Code>(isolate->builtins()->builtin( + Builtins::kHandleApiCallAsConstructor)); Handle<JSFunction> delegate = - Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE, + factory->NewFunction(factory->empty_symbol(), JS_OBJECT_TYPE, JSObject::kHeaderSize, code, true); global_context()->set_call_as_constructor_delegate(*delegate); delegate->shared()->DontAdaptArguments(); } // Initialize the out of memory slot. - global_context()->set_out_of_memory(Heap::false_value()); + global_context()->set_out_of_memory(heap->false_value()); // Initialize the data slot. - global_context()->set_data(Heap::undefined_value()); + global_context()->set_data(heap->undefined_value()); } -bool Genesis::CompileBuiltin(int index) { +bool Genesis::CompileBuiltin(Isolate* isolate, int index) { Vector<const char> name = Natives::GetScriptName(index); - Handle<String> source_code = Bootstrapper::NativesSourceLookup(index); + Handle<String> source_code = + isolate->bootstrapper()->NativesSourceLookup(index); + return CompileNative(name, source_code); +} + + +bool Genesis::CompileExperimentalBuiltin(Isolate* isolate, int index) { + Vector<const char> name = ExperimentalNatives::GetScriptName(index); + Factory* factory = isolate->factory(); + Handle<String> source_code = + factory->NewStringFromAscii( + ExperimentalNatives::GetRawScriptSource(index)); return CompileNative(name, source_code); } bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) { HandleScope scope; + Isolate* isolate = source->GetIsolate(); #ifdef ENABLE_DEBUGGER_SUPPORT - Debugger::set_compiling_natives(true); + isolate->debugger()->set_compiling_natives(true); #endif bool result = CompileScriptCached(name, source, NULL, NULL, - Handle<Context>(Top::context()), + Handle<Context>(isolate->context()), true); - ASSERT(Top::has_pending_exception() != result); - if (!result) Top::clear_pending_exception(); + ASSERT(isolate->has_pending_exception() != result); + if (!result) isolate->clear_pending_exception(); #ifdef ENABLE_DEBUGGER_SUPPORT - Debugger::set_compiling_natives(false); + isolate->debugger()->set_compiling_natives(false); #endif return result; } @@ -986,6 +1235,7 @@ bool Genesis::CompileScriptCached(Vector<const char> name, v8::Extension* extension, Handle<Context> top_context, bool use_runtime_context) { + Factory* factory = source->GetIsolate()->factory(); HandleScope scope; Handle<SharedFunctionInfo> function_info; @@ -993,7 +1243,7 @@ bool Genesis::CompileScriptCached(Vector<const char> name, // function and insert it into the cache. if (cache == NULL || !cache->Lookup(name, &function_info)) { ASSERT(source->IsAsciiRepresentation()); - Handle<String> script_name = Factory::NewStringFromUtf8(name); + Handle<String> script_name = factory->NewStringFromUtf8(name); function_info = Compiler::Compile( source, script_name, @@ -1016,7 +1266,7 @@ bool Genesis::CompileScriptCached(Vector<const char> name, ? Handle<Context>(top_context->runtime_context()) : top_context); Handle<JSFunction> fun = - Factory::NewFunctionFromSharedFunctionInfo(function_info, context); + factory->NewFunctionFromSharedFunctionInfo(function_info, context); // Call function using either the runtime object or the global // object as the receiver. Provide no parameters. @@ -1025,17 +1275,19 @@ bool Genesis::CompileScriptCached(Vector<const char> name, ? top_context->builtins() : top_context->global()); bool has_pending_exception; - Handle<Object> result = - Execution::Call(fun, receiver, 0, NULL, &has_pending_exception); + Execution::Call(fun, receiver, 0, NULL, &has_pending_exception); if (has_pending_exception) return false; return true; } -#define INSTALL_NATIVE(Type, name, var) \ - Handle<String> var##_name = Factory::LookupAsciiSymbol(name); \ - global_context()->set_##var(Type::cast( \ - global_context()->builtins()->GetPropertyNoExceptionThrown(*var##_name))); +#define INSTALL_NATIVE(Type, name, var) \ + Handle<String> var##_name = factory()->LookupAsciiSymbol(name); \ + Object* var##_native = \ + global_context()->builtins()->GetPropertyNoExceptionThrown( \ + *var##_name); \ + global_context()->set_##var(Type::cast(var##_native)); + void Genesis::InstallNativeFunctions() { HandleScope scope; @@ -1055,6 +1307,13 @@ void Genesis::InstallNativeFunctions() { INSTALL_NATIVE(JSObject, "functionCache", function_cache); } +void Genesis::InstallExperimentalNativeFunctions() { + if (FLAG_harmony_proxies) { + INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap); + INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap); + } +} + #undef INSTALL_NATIVE @@ -1064,17 +1323,19 @@ bool Genesis::InstallNatives() { // Create a function for the builtins object. Allocate space for the // JavaScript builtins, a reference to the builtins object // (itself) and a reference to the global_context directly in the object. - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal)); + Handle<Code> code = Handle<Code>( + isolate()->builtins()->builtin(Builtins::kIllegal)); Handle<JSFunction> builtins_fun = - Factory::NewFunction(Factory::empty_symbol(), JS_BUILTINS_OBJECT_TYPE, - JSBuiltinsObject::kSize, code, true); + factory()->NewFunction(factory()->empty_symbol(), + JS_BUILTINS_OBJECT_TYPE, + JSBuiltinsObject::kSize, code, true); - Handle<String> name = Factory::LookupAsciiSymbol("builtins"); + Handle<String> name = factory()->LookupAsciiSymbol("builtins"); builtins_fun->shared()->set_instance_class_name(*name); // Allocate the builtins object. Handle<JSBuiltinsObject> builtins = - Handle<JSBuiltinsObject>::cast(Factory::NewGlobalObject(builtins_fun)); + Handle<JSBuiltinsObject>::cast(factory()->NewGlobalObject(builtins_fun)); builtins->set_builtins(*builtins); builtins->set_global_context(*global_context()); builtins->set_global_receiver(*builtins); @@ -1085,7 +1346,7 @@ bool Genesis::InstallNatives() { // global object. static const PropertyAttributes attributes = static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); - Handle<String> global_symbol = Factory::LookupAsciiSymbol("global"); + Handle<String> global_symbol = factory()->LookupAsciiSymbol("global"); Handle<Object> global_obj(global_context()->global()); SetLocalPropertyNoThrow(builtins, global_symbol, global_obj, attributes); @@ -1094,12 +1355,13 @@ bool Genesis::InstallNatives() { // Create a bridge function that has context in the global context. Handle<JSFunction> bridge = - Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value()); - ASSERT(bridge->context() == *Top::global_context()); + factory()->NewFunction(factory()->empty_symbol(), + factory()->undefined_value()); + ASSERT(bridge->context() == *isolate()->global_context()); // Allocate the builtins context. Handle<Context> context = - Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge); + factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge); context->set_global(*builtins); // override builtins global object global_context()->set_runtime_context(*context); @@ -1108,123 +1370,127 @@ bool Genesis::InstallNatives() { // Builtin functions for Script. Handle<JSFunction> script_fun = InstallFunction(builtins, "Script", JS_VALUE_TYPE, JSValue::kSize, - Top::initial_object_prototype(), Builtins::Illegal, - false); + isolate()->initial_object_prototype(), + Builtins::kIllegal, false); Handle<JSObject> prototype = - Factory::NewJSObject(Top::object_function(), TENURED); + factory()->NewJSObject(isolate()->object_function(), TENURED); SetPrototype(script_fun, prototype); global_context()->set_script_function(*script_fun); // Add 'source' and 'data' property to scripts. PropertyAttributes common_attributes = static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); - Handle<Proxy> proxy_source = Factory::NewProxy(&Accessors::ScriptSource); + Handle<Foreign> foreign_source = + factory()->NewForeign(&Accessors::ScriptSource); Handle<DescriptorArray> script_descriptors = - Factory::CopyAppendProxyDescriptor( - Factory::empty_descriptor_array(), - Factory::LookupAsciiSymbol("source"), - proxy_source, + factory()->CopyAppendForeignDescriptor( + factory()->empty_descriptor_array(), + factory()->LookupAsciiSymbol("source"), + foreign_source, common_attributes); - Handle<Proxy> proxy_name = Factory::NewProxy(&Accessors::ScriptName); + Handle<Foreign> foreign_name = + factory()->NewForeign(&Accessors::ScriptName); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("name"), - proxy_name, + factory()->LookupAsciiSymbol("name"), + foreign_name, common_attributes); - Handle<Proxy> proxy_id = Factory::NewProxy(&Accessors::ScriptId); + Handle<Foreign> foreign_id = factory()->NewForeign(&Accessors::ScriptId); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("id"), - proxy_id, + factory()->LookupAsciiSymbol("id"), + foreign_id, common_attributes); - Handle<Proxy> proxy_line_offset = - Factory::NewProxy(&Accessors::ScriptLineOffset); + Handle<Foreign> foreign_line_offset = + factory()->NewForeign(&Accessors::ScriptLineOffset); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("line_offset"), - proxy_line_offset, + factory()->LookupAsciiSymbol("line_offset"), + foreign_line_offset, common_attributes); - Handle<Proxy> proxy_column_offset = - Factory::NewProxy(&Accessors::ScriptColumnOffset); + Handle<Foreign> foreign_column_offset = + factory()->NewForeign(&Accessors::ScriptColumnOffset); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("column_offset"), - proxy_column_offset, + factory()->LookupAsciiSymbol("column_offset"), + foreign_column_offset, common_attributes); - Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptData); + Handle<Foreign> foreign_data = + factory()->NewForeign(&Accessors::ScriptData); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("data"), - proxy_data, + factory()->LookupAsciiSymbol("data"), + foreign_data, common_attributes); - Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType); + Handle<Foreign> foreign_type = + factory()->NewForeign(&Accessors::ScriptType); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("type"), - proxy_type, + factory()->LookupAsciiSymbol("type"), + foreign_type, common_attributes); - Handle<Proxy> proxy_compilation_type = - Factory::NewProxy(&Accessors::ScriptCompilationType); + Handle<Foreign> foreign_compilation_type = + factory()->NewForeign(&Accessors::ScriptCompilationType); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("compilation_type"), - proxy_compilation_type, + factory()->LookupAsciiSymbol("compilation_type"), + foreign_compilation_type, common_attributes); - Handle<Proxy> proxy_line_ends = - Factory::NewProxy(&Accessors::ScriptLineEnds); + Handle<Foreign> foreign_line_ends = + factory()->NewForeign(&Accessors::ScriptLineEnds); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("line_ends"), - proxy_line_ends, + factory()->LookupAsciiSymbol("line_ends"), + foreign_line_ends, common_attributes); - Handle<Proxy> proxy_context_data = - Factory::NewProxy(&Accessors::ScriptContextData); + Handle<Foreign> foreign_context_data = + factory()->NewForeign(&Accessors::ScriptContextData); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("context_data"), - proxy_context_data, + factory()->LookupAsciiSymbol("context_data"), + foreign_context_data, common_attributes); - Handle<Proxy> proxy_eval_from_script = - Factory::NewProxy(&Accessors::ScriptEvalFromScript); + Handle<Foreign> foreign_eval_from_script = + factory()->NewForeign(&Accessors::ScriptEvalFromScript); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("eval_from_script"), - proxy_eval_from_script, + factory()->LookupAsciiSymbol("eval_from_script"), + foreign_eval_from_script, common_attributes); - Handle<Proxy> proxy_eval_from_script_position = - Factory::NewProxy(&Accessors::ScriptEvalFromScriptPosition); + Handle<Foreign> foreign_eval_from_script_position = + factory()->NewForeign(&Accessors::ScriptEvalFromScriptPosition); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("eval_from_script_position"), - proxy_eval_from_script_position, + factory()->LookupAsciiSymbol("eval_from_script_position"), + foreign_eval_from_script_position, common_attributes); - Handle<Proxy> proxy_eval_from_function_name = - Factory::NewProxy(&Accessors::ScriptEvalFromFunctionName); + Handle<Foreign> foreign_eval_from_function_name = + factory()->NewForeign(&Accessors::ScriptEvalFromFunctionName); script_descriptors = - Factory::CopyAppendProxyDescriptor( + factory()->CopyAppendForeignDescriptor( script_descriptors, - Factory::LookupAsciiSymbol("eval_from_function_name"), - proxy_eval_from_function_name, + factory()->LookupAsciiSymbol("eval_from_function_name"), + foreign_eval_from_function_name, common_attributes); Handle<Map> script_map = Handle<Map>(script_fun->initial_map()); script_map->set_instance_descriptors(*script_descriptors); // Allocate the empty script. - Handle<Script> script = Factory::NewScript(Factory::empty_string()); + Handle<Script> script = factory()->NewScript(factory()->empty_string()); script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); - Heap::public_set_empty_script(*script); + heap()->public_set_empty_script(*script); } { // Builtin function for OpaqueReference -- a JSValue-based object, @@ -1232,14 +1498,52 @@ bool Genesis::InstallNatives() { // objects, that JavaScript code may not access. Handle<JSFunction> opaque_reference_fun = InstallFunction(builtins, "OpaqueReference", JS_VALUE_TYPE, - JSValue::kSize, Top::initial_object_prototype(), - Builtins::Illegal, false); + JSValue::kSize, + isolate()->initial_object_prototype(), + Builtins::kIllegal, false); Handle<JSObject> prototype = - Factory::NewJSObject(Top::object_function(), TENURED); + factory()->NewJSObject(isolate()->object_function(), TENURED); SetPrototype(opaque_reference_fun, prototype); global_context()->set_opaque_reference_function(*opaque_reference_fun); } + { // --- I n t e r n a l A r r a y --- + // An array constructor on the builtins object that works like + // the public Array constructor, except that its prototype + // doesn't inherit from Object.prototype. + // To be used only for internal work by builtins. Instances + // must not be leaked to user code. + // Only works correctly when called as a constructor. The normal + // Array code uses Array.prototype as prototype when called as + // a function. + Handle<JSFunction> array_function = + InstallFunction(builtins, + "InternalArray", + JS_ARRAY_TYPE, + JSArray::kSize, + isolate()->initial_object_prototype(), + Builtins::kArrayCode, + true); + Handle<JSObject> prototype = + factory()->NewJSObject(isolate()->object_function(), TENURED); + SetPrototype(array_function, prototype); + + array_function->shared()->set_construct_stub( + isolate()->builtins()->builtin(Builtins::kArrayConstructCode)); + array_function->shared()->DontAdaptArguments(); + + // Make "length" magic on instances. + Handle<DescriptorArray> array_descriptors = + factory()->CopyAppendForeignDescriptor( + factory()->empty_descriptor_array(), + factory()->length_symbol(), + factory()->NewForeign(&Accessors::ArrayLength), + static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE)); + + array_function->initial_map()->set_instance_descriptors( + *array_descriptors); + } + if (FLAG_disable_native_files) { PrintF("Warning: Running without installed natives!\n"); return true; @@ -1249,8 +1553,7 @@ bool Genesis::InstallNatives() { for (int i = Natives::GetDebuggerCount(); i < Natives::GetBuiltinsCount(); i++) { - Vector<const char> name = Natives::GetScriptName(i); - if (!CompileBuiltin(i)) return false; + if (!CompileBuiltin(isolate(), i)) return false; // TODO(ager): We really only need to install the JS builtin // functions on the builtins object after compiling and running // runtime.js. @@ -1270,9 +1573,9 @@ bool Genesis::InstallNatives() { InstallBuiltinFunctionIds(); // Install Function.prototype.call and apply. - { Handle<String> key = Factory::function_class_symbol(); + { Handle<String> key = factory()->function_class_symbol(); Handle<JSFunction> function = - Handle<JSFunction>::cast(GetProperty(Top::global(), key)); + Handle<JSFunction>::cast(GetProperty(isolate()->global(), key)); Handle<JSObject> proto = Handle<JSObject>(JSObject::cast(function->instance_prototype())); @@ -1280,12 +1583,12 @@ bool Genesis::InstallNatives() { Handle<JSFunction> call = InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize, Handle<JSObject>::null(), - Builtins::FunctionCall, + Builtins::kFunctionCall, false); Handle<JSFunction> apply = InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize, Handle<JSObject>::null(), - Builtins::FunctionApply, + Builtins::kFunctionApply, false); // Make sure that Function.prototype.call appears to be compiled. @@ -1314,7 +1617,7 @@ bool Genesis::InstallNatives() { // Add initial map. Handle<Map> initial_map = - Factory::NewMap(JS_ARRAY_TYPE, JSRegExpResult::kSize); + factory()->NewMap(JS_ARRAY_TYPE, JSRegExpResult::kSize); initial_map->set_constructor(*array_constructor); // Set prototype on map. @@ -1328,13 +1631,13 @@ bool Genesis::InstallNatives() { ASSERT_EQ(1, array_descriptors->number_of_descriptors()); Handle<DescriptorArray> reresult_descriptors = - Factory::NewDescriptorArray(3); + factory()->NewDescriptorArray(3); reresult_descriptors->CopyFrom(0, *array_descriptors, 0); int enum_index = 0; { - FieldDescriptor index_field(Heap::index_symbol(), + FieldDescriptor index_field(heap()->index_symbol(), JSRegExpResult::kIndexIndex, NONE, enum_index++); @@ -1342,7 +1645,7 @@ bool Genesis::InstallNatives() { } { - FieldDescriptor input_field(Heap::input_symbol(), + FieldDescriptor input_field(heap()->input_symbol(), JSRegExpResult::kInputIndex, NONE, enum_index++); @@ -1358,6 +1661,7 @@ bool Genesis::InstallNatives() { global_context()->set_regexp_result_map(*initial_map); } + #ifdef DEBUG builtins->Verify(); #endif @@ -1366,20 +1670,38 @@ bool Genesis::InstallNatives() { } +bool Genesis::InstallExperimentalNatives() { + for (int i = ExperimentalNatives::GetDebuggerCount(); + i < ExperimentalNatives::GetBuiltinsCount(); + i++) { + if (FLAG_harmony_proxies && + strcmp(ExperimentalNatives::GetScriptName(i).start(), + "native proxy.js") == 0) { + if (!CompileExperimentalBuiltin(isolate(), i)) return false; + } + } + + InstallExperimentalNativeFunctions(); + + return true; +} + + static Handle<JSObject> ResolveBuiltinIdHolder( Handle<Context> global_context, const char* holder_expr) { + Factory* factory = global_context->GetIsolate()->factory(); Handle<GlobalObject> global(global_context->global()); const char* period_pos = strchr(holder_expr, '.'); if (period_pos == NULL) { return Handle<JSObject>::cast( - GetProperty(global, Factory::LookupAsciiSymbol(holder_expr))); + GetProperty(global, factory->LookupAsciiSymbol(holder_expr))); } ASSERT_EQ(".prototype", period_pos); Vector<const char> property(holder_expr, static_cast<int>(period_pos - holder_expr)); Handle<JSFunction> function = Handle<JSFunction>::cast( - GetProperty(global, Factory::LookupSymbol(property))); + GetProperty(global, factory->LookupSymbol(property))); return Handle<JSObject>(JSObject::cast(function->prototype())); } @@ -1387,7 +1709,8 @@ static Handle<JSObject> ResolveBuiltinIdHolder( static void InstallBuiltinFunctionId(Handle<JSObject> holder, const char* function_name, BuiltinFunctionId id) { - Handle<String> name = Factory::LookupAsciiSymbol(function_name); + Factory* factory = holder->GetIsolate()->factory(); + Handle<String> name = factory->LookupAsciiSymbol(function_name); Object* function_object = holder->GetProperty(*name)->ToObjectUnchecked(); Handle<JSFunction> function(JSFunction::cast(function_object)); function->shared()->set_function_data(Smi::FromInt(id)); @@ -1414,13 +1737,14 @@ void Genesis::InstallBuiltinFunctionIds() { F(16, global_context()->regexp_function()) -static FixedArray* CreateCache(int size, JSFunction* factory) { +static FixedArray* CreateCache(int size, Handle<JSFunction> factory_function) { + Factory* factory = factory_function->GetIsolate()->factory(); // Caches are supposed to live for a long time, allocate in old space. int array_size = JSFunctionResultCache::kEntriesIndex + 2 * size; // Cannot use cast as object is not fully initialized yet. JSFunctionResultCache* cache = reinterpret_cast<JSFunctionResultCache*>( - *Factory::NewFixedArrayWithHoles(array_size, TENURED)); - cache->set(JSFunctionResultCache::kFactoryIndex, factory); + *factory->NewFixedArrayWithHoles(array_size, TENURED)); + cache->set(JSFunctionResultCache::kFactoryIndex, *factory_function); cache->MakeZeroSize(); return cache; } @@ -1433,13 +1757,13 @@ void Genesis::InstallJSFunctionResultCaches() { #undef F ; - Handle<FixedArray> caches = Factory::NewFixedArray(kNumberOfCaches, TENURED); + Handle<FixedArray> caches = FACTORY->NewFixedArray(kNumberOfCaches, TENURED); int index = 0; -#define F(size, func) do { \ - FixedArray* cache = CreateCache((size), (func)); \ - caches->set(index++, cache); \ +#define F(size, func) do { \ + FixedArray* cache = CreateCache((size), Handle<JSFunction>(func)); \ + caches->set(index++, cache); \ } while (false) JSFUNCTION_RESULT_CACHE_LIST(F); @@ -1452,19 +1776,17 @@ void Genesis::InstallJSFunctionResultCaches() { void Genesis::InitializeNormalizedMapCaches() { Handle<FixedArray> array( - Factory::NewFixedArray(NormalizedMapCache::kEntries, TENURED)); + FACTORY->NewFixedArray(NormalizedMapCache::kEntries, TENURED)); global_context()->set_normalized_map_cache(NormalizedMapCache::cast(*array)); } -int BootstrapperActive::nesting_ = 0; - - bool Bootstrapper::InstallExtensions(Handle<Context> global_context, v8::ExtensionConfiguration* extensions) { + Isolate* isolate = global_context->GetIsolate(); BootstrapperActive active; - SaveContext saved_context; - Top::set_context(*global_context); + SaveContext saved_context(isolate); + isolate->set_context(*global_context); if (!Genesis::InstallExtensions(global_context, extensions)) return false; Genesis::InstallSpecialObjects(global_context); return true; @@ -1472,20 +1794,21 @@ bool Bootstrapper::InstallExtensions(Handle<Context> global_context, void Genesis::InstallSpecialObjects(Handle<Context> global_context) { + Factory* factory = global_context->GetIsolate()->factory(); HandleScope scope; Handle<JSGlobalObject> js_global( JSGlobalObject::cast(global_context->global())); // Expose the natives in global if a name for it is specified. if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) { Handle<String> natives_string = - Factory::LookupAsciiSymbol(FLAG_expose_natives_as); + factory->LookupAsciiSymbol(FLAG_expose_natives_as); SetLocalPropertyNoThrow(js_global, natives_string, Handle<JSObject>(js_global->builtins()), DONT_ENUM); } Handle<Object> Error = GetProperty(js_global, "Error"); if (Error->IsJSObject()) { - Handle<String> name = Factory::LookupAsciiSymbol("stackTraceLimit"); + Handle<String> name = factory->LookupAsciiSymbol("stackTraceLimit"); SetLocalPropertyNoThrow(Handle<JSObject>::cast(Error), name, Handle<Smi>(Smi::FromInt(FLAG_stack_trace_limit)), @@ -1495,18 +1818,19 @@ void Genesis::InstallSpecialObjects(Handle<Context> global_context) { #ifdef ENABLE_DEBUGGER_SUPPORT // Expose the debug global object in global if a name for it is specified. if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) { + Debug* debug = Isolate::Current()->debug(); // If loading fails we just bail out without installing the // debugger but without tanking the whole context. - if (!Debug::Load()) return; + if (!debug->Load()) return; // Set the security token for the debugger context to the same as // the shell global context to allow calling between these (otherwise // exposing debug global object doesn't make much sense). - Debug::debug_context()->set_security_token( + debug->debug_context()->set_security_token( global_context->security_token()); Handle<String> debug_string = - Factory::LookupAsciiSymbol(FLAG_expose_debug_as); - Handle<Object> global_proxy(Debug::debug_context()->global_proxy()); + factory->LookupAsciiSymbol(FLAG_expose_debug_as); + Handle<Object> global_proxy(debug->debug_context()->global_proxy()); SetLocalPropertyNoThrow(js_global, debug_string, global_proxy, DONT_ENUM); } #endif @@ -1515,6 +1839,10 @@ void Genesis::InstallSpecialObjects(Handle<Context> global_context) { bool Genesis::InstallExtensions(Handle<Context> global_context, v8::ExtensionConfiguration* extensions) { + // TODO(isolates): Extensions on multiple isolates may take a little more + // effort. (The external API reads 'ignore'-- does that mean + // we can break the interface?) + // Clear coloring of extension list v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension(); while (current != NULL) { @@ -1582,17 +1910,18 @@ bool Genesis::InstallExtension(v8::RegisteredExtension* current) { for (int i = 0; i < extension->dependency_count(); i++) { if (!InstallExtension(extension->dependencies()[i])) return false; } + Isolate* isolate = Isolate::Current(); Vector<const char> source = CStrVector(extension->source()); - Handle<String> source_code = Factory::NewStringFromAscii(source); + Handle<String> source_code = isolate->factory()->NewStringFromAscii(source); bool result = CompileScriptCached(CStrVector(extension->name()), source_code, - &extensions_cache, + isolate->bootstrapper()->extensions_cache(), extension, - Handle<Context>(Top::context()), + Handle<Context>(isolate->context()), false); - ASSERT(Top::has_pending_exception() != result); + ASSERT(isolate->has_pending_exception() != result); if (!result) { - Top::clear_pending_exception(); + isolate->clear_pending_exception(); } current->set_state(v8::INSTALLED); return result; @@ -1601,9 +1930,10 @@ bool Genesis::InstallExtension(v8::RegisteredExtension* current) { bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) { HandleScope scope; + Factory* factory = builtins->GetIsolate()->factory(); for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) { Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i); - Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id)); + Handle<String> name = factory->LookupAsciiSymbol(Builtins::GetName(id)); Object* function_object = builtins->GetPropertyNoExceptionThrown(*name); Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(function_object)); @@ -1656,8 +1986,8 @@ bool Genesis::ConfigureApiObject(Handle<JSObject> object, Handle<JSObject> obj = Execution::InstantiateObject(object_template, &pending_exception); if (pending_exception) { - ASSERT(Top::has_pending_exception()); - Top::clear_pending_exception(); + ASSERT(isolate()->has_pending_exception()); + isolate()->clear_pending_exception(); return false; } TransferObject(obj, object); @@ -1705,14 +2035,16 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, break; } case MAP_TRANSITION: + case EXTERNAL_ARRAY_TRANSITION: case CONSTANT_TRANSITION: case NULL_DESCRIPTOR: // Ignore non-properties. break; case NORMAL: // Do not occur since the from object has fast properties. + case HANDLER: case INTERCEPTOR: - // No element in instance descriptors have interceptor type. + // No element in instance descriptors have proxy or interceptor type. UNREACHABLE(); break; } @@ -1748,13 +2080,14 @@ void Genesis::TransferIndexedProperties(Handle<JSObject> from, // Cloning the elements array is sufficient. Handle<FixedArray> from_elements = Handle<FixedArray>(FixedArray::cast(from->elements())); - Handle<FixedArray> to_elements = Factory::CopyFixedArray(from_elements); + Handle<FixedArray> to_elements = FACTORY->CopyFixedArray(from_elements); to->set_elements(*to_elements); } void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) { HandleScope outer; + Factory* factory = from->GetIsolate()->factory(); ASSERT(!from->IsJSArray()); ASSERT(!to->IsJSArray()); @@ -1764,29 +2097,31 @@ void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) { // Transfer the prototype (new map is needed). Handle<Map> old_to_map = Handle<Map>(to->map()); - Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map); + Handle<Map> new_to_map = factory->CopyMapDropTransitions(old_to_map); new_to_map->set_prototype(from->map()->prototype()); to->set_map(*new_to_map); } void Genesis::MakeFunctionInstancePrototypeWritable() { - // Make a new function map so all future functions - // will have settable and enumerable prototype properties. - HandleScope scope; - - Handle<DescriptorArray> function_map_descriptors = - ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE); - Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map()); - fm->set_instance_descriptors(*function_map_descriptors); - fm->set_function_with_prototype(true); - Top::context()->global_context()->set_function_map(*fm); + // The maps with writable prototype are created in CreateEmptyFunction + // and CreateStrictModeFunctionMaps respectively. Initially the maps are + // created with read-only prototype for JS builtins processing. + ASSERT(!function_instance_map_writable_prototype_.is_null()); + ASSERT(!strict_mode_function_instance_map_writable_prototype_.is_null()); + + // Replace function instance maps to make prototype writable. + global_context()->set_function_map( + *function_instance_map_writable_prototype_); + global_context()->set_strict_mode_function_map( + *strict_mode_function_instance_map_writable_prototype_); } -Genesis::Genesis(Handle<Object> global_object, +Genesis::Genesis(Isolate* isolate, + Handle<Object> global_object, v8::Handle<v8::ObjectTemplate> global_template, - v8::ExtensionConfiguration* extensions) { + v8::ExtensionConfiguration* extensions) : isolate_(isolate) { result_ = Handle<Context>::null(); // If V8 isn't running and cannot be initialized, just return. if (!V8::IsRunning() && !V8::Initialize(NULL)) return; @@ -1794,18 +2129,15 @@ Genesis::Genesis(Handle<Object> global_object, // Before creating the roots we must save the context and restore it // on all function exits. HandleScope scope; - SaveContext saved_context; + SaveContext saved_context(isolate); Handle<Context> new_context = Snapshot::NewContextFromSnapshot(); if (!new_context.is_null()) { global_context_ = - Handle<Context>::cast(GlobalHandles::Create(*new_context)); + Handle<Context>::cast(isolate->global_handles()->Create(*new_context)); AddToWeakGlobalContextList(*global_context_); - Top::set_context(*global_context_); - i::Counters::contexts_created_by_snapshot.Increment(); - JSFunction* empty_function = - JSFunction::cast(global_context_->function_map()->prototype()); - empty_function_ = Handle<JSFunction>(empty_function); + isolate->set_context(*global_context_); + isolate->counters()->contexts_created_by_snapshot()->Increment(); Handle<GlobalObject> inner_global; Handle<JSGlobalProxy> global_proxy = CreateNewGlobals(global_template, @@ -1819,7 +2151,8 @@ Genesis::Genesis(Handle<Object> global_object, } else { // We get here if there was no context snapshot. CreateRoots(); - Handle<JSFunction> empty_function = CreateEmptyFunction(); + Handle<JSFunction> empty_function = CreateEmptyFunction(isolate); + CreateStrictModeFunctionMaps(empty_function); Handle<GlobalObject> inner_global; Handle<JSGlobalProxy> global_proxy = CreateNewGlobals(global_template, global_object, &inner_global); @@ -1832,9 +2165,12 @@ Genesis::Genesis(Handle<Object> global_object, MakeFunctionInstancePrototypeWritable(); if (!ConfigureGlobalObjects(global_template)) return; - i::Counters::contexts_created_from_scratch.Increment(); + isolate->counters()->contexts_created_from_scratch()->Increment(); } + // Install experimental natives. + if (!InstallExperimentalNatives()) return; + result_ = global_context_; } @@ -1843,46 +2179,28 @@ Genesis::Genesis(Handle<Object> global_object, // Reserve space for statics needing saving and restoring. int Bootstrapper::ArchiveSpacePerThread() { - return BootstrapperActive::ArchiveSpacePerThread(); + return sizeof(NestingCounterType); } // Archive statics that are thread local. char* Bootstrapper::ArchiveState(char* to) { - return BootstrapperActive::ArchiveState(to); + *reinterpret_cast<NestingCounterType*>(to) = nesting_; + nesting_ = 0; + return to + sizeof(NestingCounterType); } // Restore statics that are thread local. char* Bootstrapper::RestoreState(char* from) { - return BootstrapperActive::RestoreState(from); + nesting_ = *reinterpret_cast<NestingCounterType*>(from); + return from + sizeof(NestingCounterType); } // Called when the top-level V8 mutex is destroyed. void Bootstrapper::FreeThreadResources() { - ASSERT(!BootstrapperActive::IsActive()); -} - - -// Reserve space for statics needing saving and restoring. -int BootstrapperActive::ArchiveSpacePerThread() { - return sizeof(nesting_); -} - - -// Archive statics that are thread local. -char* BootstrapperActive::ArchiveState(char* to) { - *reinterpret_cast<int*>(to) = nesting_; - nesting_ = 0; - return to + sizeof(nesting_); -} - - -// Restore statics that are thread local. -char* BootstrapperActive::RestoreState(char* from) { - nesting_ = *reinterpret_cast<int*>(from); - return from + sizeof(nesting_); + ASSERT(!IsActive()); } } } // namespace v8::internal |