From 7050e6fa06c0ee61124edbb5856defeffcc9af99 Mon Sep 17 00:00:00 2001 From: "dslomov@chromium.org" Date: Mon, 7 Jul 2014 13:12:29 +0000 Subject: [PATCH] Revert "Only create arguments-maps in the bootstrapper, remove now obsolete ValueType flag." This reverts commit r22240 for breaking tests on Linux. Revert "Remove SetOwnPropertyIgnoreAttribute uses from the bootstrapper" This reverts commit r22241 for breaking tests on Linux. TBR=verwaest@chromium.org Review URL: https://codereview.chromium.org/371913002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22242 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 32 +++-- src/arm64/code-stubs-arm64.cc | 58 ++++----- src/bootstrapper.cc | 205 +++++++++++++++++++----------- src/builtins.cc | 4 +- src/contexts.h | 231 ++++++++++++++++++---------------- src/factory.cc | 22 +--- src/factory.h | 2 +- src/heap.cc | 52 ++++++++ src/heap.h | 4 + src/ia32/code-stubs-ia32.cc | 53 ++++---- src/objects.cc | 49 +++++--- src/objects.h | 20 ++- src/runtime.cc | 27 ++-- src/x64/code-stubs-x64.cc | 38 +++--- test/cctest/cctest.h | 1 + test/cctest/test-alloc.cc | 1 + 16 files changed, 470 insertions(+), 329 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 526bc5525a..06c1b05815 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -2019,12 +2019,12 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT); // r0 = address of new object(s) (tagged) - // r2 = argument count (smi-tagged) + // r2 = argument count (tagged) // Get the arguments boilerplate from the current native context into r4. const int kNormalOffset = - Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); + Context::SlotOffset(Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX); const int kAliasedOffset = - Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX); + Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX); __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); @@ -2034,23 +2034,22 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { // r0 = address of new object (tagged) // r1 = mapped parameter count (tagged) - // r2 = argument count (smi-tagged) - // r4 = address of arguments map (tagged) - __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); - __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); - __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); - __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); + // r2 = argument count (tagged) + // r4 = address of boilerplate object (tagged) + // Copy the JS object part. + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { + __ ldr(r3, FieldMemOperand(r4, i)); + __ str(r3, FieldMemOperand(r0, i)); + } // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); - __ AssertNotSmi(r3); const int kCalleeOffset = JSObject::kHeaderSize + Heap::kArgumentsCalleeIndex * kPointerSize; __ str(r3, FieldMemOperand(r0, kCalleeOffset)); // Use the length (smi tagged) and set that as an in-object property too. - __ AssertSmi(r2); STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); const int kLengthOffset = JSObject::kHeaderSize + Heap::kArgumentsLengthIndex * kPointerSize; @@ -2204,18 +2203,15 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Get the arguments boilerplate from the current native context. __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); - __ ldr(r4, MemOperand( - r4, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); + __ ldr(r4, MemOperand(r4, Context::SlotOffset( + Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX))); - __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); - __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); - __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); - __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); + // Copy the JS object part. + __ CopyFields(r0, r4, d0, JSObject::kHeaderSize / kPointerSize); // Get the length (smi tagged) and set that as an in-object property too. STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); - __ AssertSmi(r1); __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + Heap::kArgumentsLengthIndex * kPointerSize)); diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc index 0e08907061..6dc564da4a 100644 --- a/src/arm64/code-stubs-arm64.cc +++ b/src/arm64/code-stubs-arm64.cc @@ -2103,42 +2103,41 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { // Get the arguments boilerplate from the current (global) context. - // x0 alloc_obj pointer to allocated objects (param map, backing - // store, arguments) - // x1 mapped_params number of mapped parameters, min(params, args) - // x2 arg_count number of function arguments - // x3 arg_count_smi number of function arguments (smi) - // x4 function function pointer - // x7 param_count number of function parameters - // x11 sloppy_args_map offset to args (or aliased args) map (uninit) - // x14 recv_arg pointer to receiver arguments + // x0 alloc_obj pointer to allocated objects (param map, backing + // store, arguments) + // x1 mapped_params number of mapped parameters, min(params, args) + // x2 arg_count number of function arguments + // x3 arg_count_smi number of function arguments (smi) + // x4 function function pointer + // x7 param_count number of function parameters + // x11 args_offset offset to args (or aliased args) boilerplate (uninit) + // x14 recv_arg pointer to receiver arguments Register global_object = x10; Register global_ctx = x10; - Register sloppy_args_map = x11; - Register aliased_args_map = x10; + Register args_offset = x11; + Register aliased_args_offset = x10; __ Ldr(global_object, GlobalObjectMemOperand()); __ Ldr(global_ctx, FieldMemOperand(global_object, GlobalObject::kNativeContextOffset)); - __ Ldr(sloppy_args_map, - ContextMemOperand(global_ctx, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); - __ Ldr(aliased_args_map, - ContextMemOperand(global_ctx, Context::ALIASED_ARGUMENTS_MAP_INDEX)); + __ Ldr(args_offset, + ContextMemOperand(global_ctx, + Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX)); + __ Ldr(aliased_args_offset, + ContextMemOperand(global_ctx, + Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX)); __ Cmp(mapped_params, 0); - __ CmovX(sloppy_args_map, aliased_args_map, ne); + __ CmovX(args_offset, aliased_args_offset, ne); // Copy the JS object part. - __ Str(sloppy_args_map, FieldMemOperand(alloc_obj, JSObject::kMapOffset)); - __ LoadRoot(x10, Heap::kEmptyFixedArrayRootIndex); - __ Str(x10, FieldMemOperand(alloc_obj, JSObject::kPropertiesOffset)); - __ Str(x10, FieldMemOperand(alloc_obj, JSObject::kElementsOffset)); + __ CopyFields(alloc_obj, args_offset, CPURegList(x10, x12, x13), + JSObject::kHeaderSize / kPointerSize); // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); const int kCalleeOffset = JSObject::kHeaderSize + Heap::kArgumentsCalleeIndex * kPointerSize; - __ AssertNotSmi(function); __ Str(function, FieldMemOperand(alloc_obj, kCalleeOffset)); // Use the length and set that as an in-object property. @@ -2339,24 +2338,25 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Get the arguments boilerplate from the current (native) context. Register global_object = x10; Register global_ctx = x10; - Register strict_args_map = x4; + Register args_offset = x4; __ Ldr(global_object, GlobalObjectMemOperand()); __ Ldr(global_ctx, FieldMemOperand(global_object, GlobalObject::kNativeContextOffset)); - __ Ldr(strict_args_map, - ContextMemOperand(global_ctx, Context::STRICT_ARGUMENTS_MAP_INDEX)); + __ Ldr(args_offset, + ContextMemOperand(global_ctx, + Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX)); // x0 alloc_obj pointer to allocated objects: parameter array and // arguments object // x1 param_count_smi number of parameters passed to function (smi) // x2 params pointer to parameters // x3 function function pointer - // x4 strict_args_map offset to arguments map + // x4 args_offset offset to arguments boilerplate // x13 param_count number of parameters passed to function - __ Str(strict_args_map, FieldMemOperand(alloc_obj, JSObject::kMapOffset)); - __ LoadRoot(x5, Heap::kEmptyFixedArrayRootIndex); - __ Str(x5, FieldMemOperand(alloc_obj, JSObject::kPropertiesOffset)); - __ Str(x5, FieldMemOperand(alloc_obj, JSObject::kElementsOffset)); + + // Copy the JS object part. + __ CopyFields(alloc_obj, args_offset, CPURegList(x5, x6, x7), + JSObject::kHeaderSize / kPointerSize); // Set the smi-tagged length as an in-object property. STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index bbe320193e..42e3e6993b 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -769,17 +769,16 @@ Handle Genesis::CreateNewGlobals( Handle name = Handle(heap()->empty_string()); Handle code = Handle(isolate()->builtins()->builtin( Builtins::kIllegal)); - Handle prototype = - factory()->NewFunctionPrototype(isolate()->object_function()); js_global_object_function = factory()->NewFunction( - name, code, prototype, JS_GLOBAL_OBJECT_TYPE, JSGlobalObject::kSize); -#ifdef DEBUG - LookupIterator it(prototype, factory()->constructor_string(), - LookupIterator::CHECK_OWN_REAL); - Handle value = JSReceiver::GetProperty(&it).ToHandleChecked(); - ASSERT(it.IsFound()); - ASSERT_EQ(*isolate()->object_function(), *value); -#endif + name, code, JS_GLOBAL_OBJECT_TYPE, JSGlobalObject::kSize); + // Change the constructor property of the prototype of the + // hidden global function to refer to the Object function. + Handle prototype = + Handle( + JSObject::cast(js_global_object_function->instance_prototype())); + JSObject::SetOwnPropertyIgnoreAttributes( + prototype, factory()->constructor_string(), + isolate()->object_function(), NONE).Check(); } else { Handle js_global_object_constructor( FunctionTemplateInfo::cast(js_global_object_template->constructor())); @@ -1134,57 +1133,80 @@ void Genesis::InitializeGlobal(Handle global_object, InstallFunction(global, "WeakSet", JS_WEAK_SET_TYPE, JSWeakSet::kSize, isolate->initial_object_prototype(), Builtins::kIllegal); - { // --- sloppy arguments map + { // --- arguments_boilerplate_ // Make sure we can recognize argument objects at runtime. // This is done by introducing an anonymous function with // class_name equals 'Arguments'. Handle arguments_string = factory->InternalizeOneByteString( STATIC_ASCII_VECTOR("Arguments")); Handle code(isolate->builtins()->builtin(Builtins::kIllegal)); + Handle function = factory->NewFunctionWithoutPrototype( arguments_string, code); - function->shared()->set_instance_class_name(*arguments_string); - - Handle map = - factory->NewMap(JS_OBJECT_TYPE, Heap::kSloppyArgumentsObjectSize); - // Create the descriptor array for the arguments object. - Map::EnsureDescriptorSlack(map, 2); - - { // length - FieldDescriptor d(factory->length_string(), Heap::kArgumentsLengthIndex, - DONT_ENUM, Representation::Tagged()); - map->AppendDescriptor(&d); - } - { // callee - FieldDescriptor d(factory->callee_string(), Heap::kArgumentsCalleeIndex, - DONT_ENUM, Representation::Tagged()); - map->AppendDescriptor(&d); - } - - map->set_function_with_prototype(true); - map->set_prototype(native_context()->object_function()->prototype()); - map->set_pre_allocated_property_fields(2); - map->set_inobject_properties(2); - native_context()->set_sloppy_arguments_map(*map); - ASSERT(!function->has_initial_map()); - function->set_initial_map(*map); - map->set_constructor(*function); + function->shared()->set_instance_class_name(*arguments_string); + function->shared()->set_expected_nof_properties(2); + function->set_prototype_or_initial_map( + native_context()->object_function()->prototype()); + Handle result = factory->NewJSObject(function); - ASSERT(map->inobject_properties() > Heap::kArgumentsCalleeIndex); - ASSERT(map->inobject_properties() > Heap::kArgumentsLengthIndex); - ASSERT(!map->is_dictionary_map()); - ASSERT(IsFastObjectElementsKind(map->elements_kind())); + native_context()->set_sloppy_arguments_boilerplate(*result); + // Note: length must be added as the first property and + // callee must be added as the second property. + JSObject::AddProperty( + result, factory->length_string(), + factory->undefined_value(), DONT_ENUM, + Object::FORCE_TAGGED, FORCE_FIELD); + JSObject::AddProperty( + result, factory->callee_string(), + factory->undefined_value(), DONT_ENUM, + Object::FORCE_TAGGED, FORCE_FIELD); + +#ifdef DEBUG + LookupResult lookup(isolate); + result->LookupOwn(factory->callee_string(), &lookup); + ASSERT(lookup.IsField()); + ASSERT(lookup.GetFieldIndex().property_index() == + Heap::kArgumentsCalleeIndex); + + result->LookupOwn(factory->length_string(), &lookup); + ASSERT(lookup.IsField()); + ASSERT(lookup.GetFieldIndex().property_index() == + 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->HasFastObjectElements()); +#endif } - { // --- aliased arguments map - Handle map = Map::Copy(isolate->sloppy_arguments_map()); - map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS); - ASSERT_EQ(2, map->pre_allocated_property_fields()); - native_context()->set_aliased_arguments_map(*map); + { // --- aliased_arguments_boilerplate_ + // Set up a well-formed parameter map to make assertions happy. + Handle elements = factory->NewFixedArray(2); + elements->set_map(heap->sloppy_arguments_elements_map()); + Handle array; + array = factory->NewFixedArray(0); + elements->set(0, *array); + array = factory->NewFixedArray(0); + elements->set(1, *array); + + Handle old_map( + native_context()->sloppy_arguments_boilerplate()->map()); + Handle new_map = Map::Copy(old_map); + new_map->set_pre_allocated_property_fields(2); + Handle result = factory->NewJSObjectFromMap(new_map); + // Set elements kind after allocating the object because + // NewJSObjectFromMap assumes a fast elements map. + new_map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS); + result->set_elements(*elements); + ASSERT(result->HasSloppyArgumentsElements()); + native_context()->set_aliased_arguments_boilerplate(*result); } - { // --- strict mode arguments map + { // --- strict mode arguments boilerplate const PropertyAttributes attributes = static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY); @@ -1207,16 +1229,20 @@ void Genesis::InitializeGlobal(Handle global_object, Map::EnsureDescriptorSlack(map, 3); { // length - FieldDescriptor d(factory->length_string(), Heap::kArgumentsLengthIndex, - DONT_ENUM, Representation::Tagged()); + FieldDescriptor d( + factory->length_string(), 0, DONT_ENUM, Representation::Tagged()); map->AppendDescriptor(&d); } { // callee - CallbacksDescriptor d(factory->callee_string(), callee, attributes); + CallbacksDescriptor d(factory->callee_string(), + callee, + attributes); map->AppendDescriptor(&d); } { // caller - CallbacksDescriptor d(factory->caller_string(), caller, attributes); + CallbacksDescriptor d(factory->caller_string(), + caller, + attributes); map->AppendDescriptor(&d); } @@ -1227,13 +1253,29 @@ void Genesis::InitializeGlobal(Handle global_object, // Copy constructor from the sloppy arguments boilerplate. map->set_constructor( - native_context()->sloppy_arguments_map()->constructor()); + native_context()->sloppy_arguments_boilerplate()->map()->constructor()); - native_context()->set_strict_arguments_map(*map); + // Allocate the arguments boilerplate object. + Handle result = factory->NewJSObjectFromMap(map); + native_context()->set_strict_arguments_boilerplate(*result); - ASSERT(map->inobject_properties() > Heap::kArgumentsLengthIndex); - ASSERT(!map->is_dictionary_map()); - ASSERT(IsFastObjectElementsKind(map->elements_kind())); +#ifdef DEBUG + LookupResult lookup(isolate); + result->LookupOwn(factory->length_string(), &lookup); + ASSERT(lookup.IsField()); + ASSERT(lookup.GetFieldIndex().property_index() == + Heap::kArgumentsLengthIndex); + + Handle length_value = Object::GetProperty( + result, factory->length_string()).ToHandleChecked(); + ASSERT_EQ(heap->undefined_value(), *length_value); + + ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex); + + // Check the state of the object. + ASSERT(result->HasFastProperties()); + ASSERT(result->HasFastObjectElements()); +#endif } { // --- context extension @@ -2150,34 +2192,45 @@ bool Bootstrapper::InstallExtensions(Handle native_context, bool Genesis::InstallSpecialObjects(Handle native_context) { Isolate* isolate = native_context->GetIsolate(); - // Don't install extensions into the snapshot. - if (isolate->serializer_enabled()) return true; - Factory* factory = isolate->factory(); HandleScope scope(isolate); Handle global(JSGlobalObject::cast( native_context->global_object())); - - Handle Error = Handle::cast( - Object::GetProperty(isolate, global, "Error").ToHandleChecked()); - Handle name = - factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("stackTraceLimit")); - Handle stack_trace_limit(Smi::FromInt(FLAG_stack_trace_limit), isolate); - JSObject::AddProperty(Error, name, stack_trace_limit, NONE); - // 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 natives = factory->InternalizeUtf8String(FLAG_expose_natives_as); - JSObject::AddProperty(global, natives, handle(global->builtins()), - DONT_ENUM); + RETURN_ON_EXCEPTION_VALUE( + isolate, + JSObject::SetOwnPropertyIgnoreAttributes( + global, natives, Handle(global->builtins()), DONT_ENUM), + false); + } + + Handle Error = Object::GetProperty( + isolate, global, "Error").ToHandleChecked(); + if (Error->IsJSObject()) { + Handle name = factory->InternalizeOneByteString( + STATIC_ASCII_VECTOR("stackTraceLimit")); + Handle stack_trace_limit( + Smi::FromInt(FLAG_stack_trace_limit), isolate); + RETURN_ON_EXCEPTION_VALUE( + isolate, + JSObject::SetOwnPropertyIgnoreAttributes( + Handle::cast(Error), name, stack_trace_limit, NONE), + false); } // Expose the stack trace symbol to native JS. - JSObject::AddProperty(handle(global->builtins()), - factory->InternalizeOneByteString( - STATIC_ASCII_VECTOR("stack_trace_symbol")), - factory->stack_trace_symbol(), NONE); + RETURN_ON_EXCEPTION_VALUE( + isolate, + JSObject::SetOwnPropertyIgnoreAttributes( + handle(native_context->builtins(), isolate), + factory->InternalizeOneByteString( + STATIC_ASCII_VECTOR("stack_trace_symbol")), + factory->stack_trace_symbol(), + NONE), + false); // 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) { @@ -2193,7 +2246,11 @@ bool Genesis::InstallSpecialObjects(Handle native_context) { Handle debug_string = factory->InternalizeUtf8String(FLAG_expose_debug_as); Handle global_proxy(debug_context->global_proxy(), isolate); - JSObject::AddProperty(global, debug_string, global_proxy, DONT_ENUM); + RETURN_ON_EXCEPTION_VALUE( + isolate, + JSObject::SetOwnPropertyIgnoreAttributes( + global, debug_string, global_proxy, DONT_ENUM), + false); } return true; } diff --git a/src/builtins.cc b/src/builtins.cc index 94ff13e072..33bd5dfdcb 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -643,8 +643,8 @@ BUILTIN(ArraySlice) { } else { // Array.slice(arguments, ...) is quite a common idiom (notably more // than 50% of invocations in Web apps). Treat it in C++ as well. - Map* arguments_map = - isolate->context()->native_context()->sloppy_arguments_map(); + Map* arguments_map = isolate->context()->native_context()-> + sloppy_arguments_boilerplate()->map(); bool is_arguments_object_with_fast_elements = receiver->IsJSObject() && diff --git a/src/contexts.h b/src/contexts.h index 08773b79a5..1ee5a6f891 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -73,114 +73,122 @@ enum BindingFlags { // must always be allocated via Heap::AllocateContext() or // Factory::NewContext. -#define NATIVE_CONTEXT_FIELDS(V) \ - V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \ - V(SECURITY_TOKEN_INDEX, Object, security_token) \ - V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \ - V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \ - V(STRING_FUNCTION_INDEX, JSFunction, string_function) \ - V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \ - V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \ - V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \ - V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \ - V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ - V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \ - V(DATE_FUNCTION_INDEX, JSFunction, date_function) \ - V(JSON_OBJECT_INDEX, JSObject, json_object) \ - V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \ - V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \ - V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \ - V(CREATE_DATE_FUN_INDEX, JSFunction, create_date_fun) \ - V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \ - V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \ - V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \ - V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \ - V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \ - V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \ - V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \ - V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \ - V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \ - V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \ - V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \ - V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun) \ - V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \ - V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun) \ - V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun) \ - V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun) \ - V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \ - V(FLOAT32_ARRAY_FUN_INDEX, JSFunction, float32_array_fun) \ - V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \ - V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun) \ - V(INT8_ARRAY_EXTERNAL_MAP_INDEX, Map, int8_array_external_map) \ - V(UINT8_ARRAY_EXTERNAL_MAP_INDEX, Map, uint8_array_external_map) \ - V(INT16_ARRAY_EXTERNAL_MAP_INDEX, Map, int16_array_external_map) \ - V(UINT16_ARRAY_EXTERNAL_MAP_INDEX, Map, uint16_array_external_map) \ - V(INT32_ARRAY_EXTERNAL_MAP_INDEX, Map, int32_array_external_map) \ - V(UINT32_ARRAY_EXTERNAL_MAP_INDEX, Map, uint32_array_external_map) \ - V(FLOAT32_ARRAY_EXTERNAL_MAP_INDEX, Map, float32_array_external_map) \ - V(FLOAT64_ARRAY_EXTERNAL_MAP_INDEX, Map, float64_array_external_map) \ - V(UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX, Map, \ - uint8_clamped_array_external_map) \ - V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \ - V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map) \ - V(SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, Map, \ - sloppy_function_with_readonly_prototype_map) \ - V(STRICT_FUNCTION_MAP_INDEX, Map, strict_function_map) \ - V(SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \ - sloppy_function_without_prototype_map) \ - V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \ - strict_function_without_prototype_map) \ - V(BOUND_FUNCTION_MAP_INDEX, Map, bound_function_map) \ - V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map) \ - V(SLOPPY_ARGUMENTS_MAP_INDEX, Map, sloppy_arguments_map) \ - V(ALIASED_ARGUMENTS_MAP_INDEX, Map, aliased_arguments_map) \ - V(STRICT_ARGUMENTS_MAP_INDEX, Map, strict_arguments_map) \ - V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \ - V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \ - V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \ - V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun) \ - V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \ - V(JSFUNCTION_RESULT_CACHES_INDEX, FixedArray, jsfunction_result_caches) \ - V(NORMALIZED_MAP_CACHE_INDEX, NormalizedMapCache, normalized_map_cache) \ - V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \ - V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \ - V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \ - call_as_constructor_delegate) \ - V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \ - V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \ - V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \ - V(MAP_CACHE_INDEX, Object, map_cache) \ - V(EMBEDDER_DATA_INDEX, FixedArray, embedder_data) \ - V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \ - V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \ - error_message_for_code_gen_from_strings) \ - V(IS_PROMISE_INDEX, JSFunction, is_promise) \ - V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \ - V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \ - V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \ - V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain) \ - V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \ - V(PROMISE_THEN_INDEX, JSFunction, promise_then) \ - V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \ - to_complete_property_descriptor) \ - V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \ - V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap) \ - V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap) \ - V(PROXY_ENUMERATE_INDEX, JSFunction, proxy_enumerate) \ - V(OBSERVERS_NOTIFY_CHANGE_INDEX, JSFunction, observers_notify_change) \ - V(OBSERVERS_ENQUEUE_SPLICE_INDEX, JSFunction, observers_enqueue_splice) \ - V(OBSERVERS_BEGIN_SPLICE_INDEX, JSFunction, observers_begin_perform_splice) \ - V(OBSERVERS_END_SPLICE_INDEX, JSFunction, observers_end_perform_splice) \ - V(NATIVE_OBJECT_OBSERVE_INDEX, JSFunction, native_object_observe) \ - V(NATIVE_OBJECT_GET_NOTIFIER_INDEX, JSFunction, native_object_get_notifier) \ - V(NATIVE_OBJECT_NOTIFIER_PERFORM_CHANGE, JSFunction, \ - native_object_notifier_perform_change) \ - V(SLOPPY_GENERATOR_FUNCTION_MAP_INDEX, Map, sloppy_generator_function_map) \ - V(STRICT_GENERATOR_FUNCTION_MAP_INDEX, Map, strict_generator_function_map) \ - V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, generator_object_prototype_map) \ - V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \ - V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \ - V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map) \ +#define NATIVE_CONTEXT_FIELDS(V) \ + V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \ + V(SECURITY_TOKEN_INDEX, Object, security_token) \ + V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \ + V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \ + V(STRING_FUNCTION_INDEX, JSFunction, string_function) \ + V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \ + V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \ + V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \ + V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \ + V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ + V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \ + V(DATE_FUNCTION_INDEX, JSFunction, date_function) \ + V(JSON_OBJECT_INDEX, JSObject, json_object) \ + V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \ + V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \ + V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \ + V(CREATE_DATE_FUN_INDEX, JSFunction, create_date_fun) \ + V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \ + V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \ + V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \ + V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \ + V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \ + V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \ + V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \ + V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \ + V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \ + V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \ + V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \ + V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun) \ + V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \ + V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun) \ + V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun) \ + V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun) \ + V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \ + V(FLOAT32_ARRAY_FUN_INDEX, JSFunction, float32_array_fun) \ + V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \ + V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun) \ + V(INT8_ARRAY_EXTERNAL_MAP_INDEX, Map, int8_array_external_map) \ + V(UINT8_ARRAY_EXTERNAL_MAP_INDEX, Map, uint8_array_external_map) \ + V(INT16_ARRAY_EXTERNAL_MAP_INDEX, Map, int16_array_external_map) \ + V(UINT16_ARRAY_EXTERNAL_MAP_INDEX, Map, uint16_array_external_map) \ + V(INT32_ARRAY_EXTERNAL_MAP_INDEX, Map, int32_array_external_map) \ + V(UINT32_ARRAY_EXTERNAL_MAP_INDEX, Map, uint32_array_external_map) \ + V(FLOAT32_ARRAY_EXTERNAL_MAP_INDEX, Map, float32_array_external_map) \ + V(FLOAT64_ARRAY_EXTERNAL_MAP_INDEX, Map, float64_array_external_map) \ + V(UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX, Map, \ + uint8_clamped_array_external_map) \ + V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \ + V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map) \ + V(SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, Map, \ + sloppy_function_with_readonly_prototype_map) \ + V(STRICT_FUNCTION_MAP_INDEX, Map, strict_function_map) \ + V(SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \ + sloppy_function_without_prototype_map) \ + V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \ + strict_function_without_prototype_map) \ + V(BOUND_FUNCTION_MAP_INDEX, Map, bound_function_map) \ + V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\ + V(SLOPPY_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \ + sloppy_arguments_boilerplate) \ + V(ALIASED_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \ + aliased_arguments_boilerplate) \ + V(STRICT_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \ + strict_arguments_boilerplate) \ + V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \ + V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \ + V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \ + V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun) \ + V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \ + V(JSFUNCTION_RESULT_CACHES_INDEX, FixedArray, jsfunction_result_caches) \ + V(NORMALIZED_MAP_CACHE_INDEX, NormalizedMapCache, normalized_map_cache) \ + V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \ + V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \ + V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \ + call_as_constructor_delegate) \ + V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \ + V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \ + V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \ + V(MAP_CACHE_INDEX, Object, map_cache) \ + V(EMBEDDER_DATA_INDEX, FixedArray, embedder_data) \ + V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \ + V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \ + error_message_for_code_gen_from_strings) \ + V(IS_PROMISE_INDEX, JSFunction, is_promise) \ + V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \ + V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \ + V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \ + V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain) \ + V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \ + V(PROMISE_THEN_INDEX, JSFunction, promise_then) \ + V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \ + to_complete_property_descriptor) \ + V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \ + V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap) \ + V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap) \ + V(PROXY_ENUMERATE_INDEX, JSFunction, proxy_enumerate) \ + V(OBSERVERS_NOTIFY_CHANGE_INDEX, JSFunction, observers_notify_change) \ + V(OBSERVERS_ENQUEUE_SPLICE_INDEX, JSFunction, observers_enqueue_splice) \ + V(OBSERVERS_BEGIN_SPLICE_INDEX, JSFunction, \ + observers_begin_perform_splice) \ + V(OBSERVERS_END_SPLICE_INDEX, JSFunction, \ + observers_end_perform_splice) \ + V(NATIVE_OBJECT_OBSERVE_INDEX, JSFunction, \ + native_object_observe) \ + V(NATIVE_OBJECT_GET_NOTIFIER_INDEX, JSFunction, \ + native_object_get_notifier) \ + V(NATIVE_OBJECT_NOTIFIER_PERFORM_CHANGE, JSFunction, \ + native_object_notifier_perform_change) \ + V(SLOPPY_GENERATOR_FUNCTION_MAP_INDEX, Map, sloppy_generator_function_map) \ + V(STRICT_GENERATOR_FUNCTION_MAP_INDEX, Map, strict_generator_function_map) \ + V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \ + generator_object_prototype_map) \ + V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \ + V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \ + V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map) \ V(ITERATOR_SYMBOL_INDEX, Symbol, iterator_symbol) // JSFunctions are pairs (context, function code), sometimes also called @@ -255,9 +263,9 @@ class Context: public FixedArray { // These slots are only in native contexts. GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS, SECURITY_TOKEN_INDEX, - SLOPPY_ARGUMENTS_MAP_INDEX, - ALIASED_ARGUMENTS_MAP_INDEX, - STRICT_ARGUMENTS_MAP_INDEX, + SLOPPY_ARGUMENTS_BOILERPLATE_INDEX, + ALIASED_ARGUMENTS_BOILERPLATE_INDEX, + STRICT_ARGUMENTS_BOILERPLATE_INDEX, REGEXP_RESULT_MAP_INDEX, SLOPPY_FUNCTION_MAP_INDEX, SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, @@ -367,6 +375,7 @@ class Context: public FixedArray { // Total number of slots. NATIVE_CONTEXT_SLOTS, + FIRST_WEAK_SLOT = OPTIMIZED_FUNCTIONS_LIST }; diff --git a/src/factory.cc b/src/factory.cc index 8c08ba1587..a09c7841e3 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -4,7 +4,6 @@ #include "src/factory.h" -#include "src/allocation-site-scopes.h" #include "src/conversions.h" #include "src/isolate-inl.h" #include "src/macro-assembler.h" @@ -2087,24 +2086,11 @@ Handle Factory::NewDebugInfo(Handle shared) { } -Handle Factory::NewArgumentsObject(Handle callee, +Handle Factory::NewArgumentsObject(Handle callee, int length) { - bool strict_mode_callee = callee->shared()->strict_mode() == STRICT; - Handle map = strict_mode_callee ? isolate()->strict_arguments_map() - : isolate()->sloppy_arguments_map(); - - AllocationSiteUsageContext context(isolate(), Handle(), - false); - ASSERT(!isolate()->has_pending_exception()); - Handle result = NewJSObjectFromMap(map); - Handle value(Smi::FromInt(length), isolate()); - JSReceiver::SetProperty(result, length_string(), value, NONE, STRICT) - .Assert(); - if (!strict_mode_callee) { - JSReceiver::SetProperty(result, callee_string(), callee, NONE, STRICT) - .Assert(); - } - return result; + CALL_HEAP_FUNCTION( + isolate(), + isolate()->heap()->AllocateArgumentsObject(*callee, length), JSObject); } diff --git a/src/factory.h b/src/factory.h index b91b246c70..3736b4bd6a 100644 --- a/src/factory.h +++ b/src/factory.h @@ -361,7 +361,7 @@ class Factory V8_FINAL { return NewJSObjectFromMap(neander_map()); } - Handle NewArgumentsObject(Handle callee, int length); + Handle NewArgumentsObject(Handle callee, int length); // JS objects are pretenured when allocated by the bootstrapper and // runtime. diff --git a/src/heap.cc b/src/heap.cc index 2fa7702db0..d390788d26 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -3569,6 +3569,58 @@ AllocationResult Heap::Allocate(Map* map, AllocationSpace space, } +AllocationResult Heap::AllocateArgumentsObject(Object* callee, int length) { + // To get fast allocation and map sharing for arguments objects we + // allocate them based on an arguments boilerplate. + + JSObject* boilerplate; + int arguments_object_size; + bool strict_mode_callee = callee->IsJSFunction() && + JSFunction::cast(callee)->shared()->strict_mode() == STRICT; + if (strict_mode_callee) { + boilerplate = + isolate()->context()->native_context()->strict_arguments_boilerplate(); + arguments_object_size = kStrictArgumentsObjectSize; + } else { + boilerplate = + isolate()->context()->native_context()->sloppy_arguments_boilerplate(); + arguments_object_size = kSloppyArgumentsObjectSize; + } + + // Check that the size of the boilerplate matches our + // expectations. The ArgumentsAccessStub::GenerateNewObject relies + // on the size being a known constant. + ASSERT(arguments_object_size == boilerplate->map()->instance_size()); + + // Do the allocation. + HeapObject* result; + { AllocationResult allocation = + AllocateRaw(arguments_object_size, NEW_SPACE, OLD_POINTER_SPACE); + if (!allocation.To(&result)) return allocation; + } + + // Copy the content. The arguments boilerplate doesn't have any + // fields that point to new space so it's safe to skip the write + // barrier here. + CopyBlock(result->address(), boilerplate->address(), JSObject::kHeaderSize); + + // Set the length property. + JSObject* js_obj = JSObject::cast(result); + js_obj->InObjectPropertyAtPut( + kArgumentsLengthIndex, Smi::FromInt(length), SKIP_WRITE_BARRIER); + // Set the callee property for sloppy mode arguments object only. + if (!strict_mode_callee) { + js_obj->InObjectPropertyAtPut(kArgumentsCalleeIndex, callee); + } + + // Check the state of the object + ASSERT(js_obj->HasFastProperties()); + ASSERT(js_obj->HasFastObjectElements()); + + return js_obj; +} + + void Heap::InitializeJSObjectFromMap(JSObject* obj, FixedArray* properties, Map* map) { diff --git a/src/heap.h b/src/heap.h index a6a14f6a60..31df8537e7 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1486,6 +1486,10 @@ class Heap { int length, PretenureFlag pretenure = NOT_TENURED); + // Allocates an arguments object - optionally with an elements array. + MUST_USE_RESULT AllocationResult AllocateArgumentsObject( + Object* callee, int length); + // Copy the code and scope info part of the code object, but insert // the provided data as the relocation information. MUST_USE_RESULT AllocationResult CopyCode(Code* code, diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index e3f1aa63f8..8a05e00763 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -1036,7 +1036,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { __ mov(Operand(esp, 2 * kPointerSize), edx); // ebx = parameter count (tagged) - // ecx = argument count (smi-tagged) + // ecx = argument count (tagged) // esp[4] = parameter count (tagged) // esp[8] = address of receiver argument // Compute the mapped parameter count = min(ebx, ecx) in ebx. @@ -1069,52 +1069,47 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { __ Allocate(ebx, eax, edx, edi, &runtime, TAG_OBJECT); // eax = address of new object(s) (tagged) - // ecx = argument count (smi-tagged) + // ecx = argument count (tagged) // esp[0] = mapped parameter count (tagged) // esp[8] = parameter count (tagged) // esp[12] = address of receiver argument - // Get the arguments map from the current native context into edi. - Label has_mapped_parameters, instantiate; + // Get the arguments boilerplate from the current native context into edi. + Label has_mapped_parameters, copy; __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset)); __ mov(ebx, Operand(esp, 0 * kPointerSize)); __ test(ebx, ebx); __ j(not_zero, &has_mapped_parameters, Label::kNear); - __ mov( - edi, - Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX))); - __ jmp(&instantiate, Label::kNear); + __ mov(edi, Operand(edi, + Context::SlotOffset(Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX))); + __ jmp(©, Label::kNear); __ bind(&has_mapped_parameters); - __ mov( - edi, - Operand(edi, Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX))); - __ bind(&instantiate); + __ mov(edi, Operand(edi, + Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX))); + __ bind(©); // eax = address of new object (tagged) // ebx = mapped parameter count (tagged) - // ecx = argument count (smi-tagged) - // edi = address of arguments map (tagged) + // ecx = argument count (tagged) + // edi = address of boilerplate object (tagged) // esp[0] = mapped parameter count (tagged) // esp[8] = parameter count (tagged) // esp[12] = address of receiver argument // Copy the JS object part. - __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); - __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), - masm->isolate()->factory()->empty_fixed_array()); - __ mov(FieldOperand(eax, JSObject::kElementsOffset), - masm->isolate()->factory()->empty_fixed_array()); + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { + __ mov(edx, FieldOperand(edi, i)); + __ mov(FieldOperand(eax, i), edx); + } // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ mov(edx, Operand(esp, 4 * kPointerSize)); - __ AssertNotSmi(edx); __ mov(FieldOperand(eax, JSObject::kHeaderSize + Heap::kArgumentsCalleeIndex * kPointerSize), edx); // Use the length (smi tagged) and set that as an in-object property too. - __ AssertSmi(ecx); STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); __ mov(FieldOperand(eax, JSObject::kHeaderSize + Heap::kArgumentsLengthIndex * kPointerSize), @@ -1271,22 +1266,22 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Do the allocation of both objects in one go. __ Allocate(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); - // Get the arguments map from the current native context. + // Get the arguments boilerplate from the current native context. __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset)); - const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX); + const int offset = + Context::SlotOffset(Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX); __ mov(edi, Operand(edi, offset)); - __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); - __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), - masm->isolate()->factory()->empty_fixed_array()); - __ mov(FieldOperand(eax, JSObject::kElementsOffset), - masm->isolate()->factory()->empty_fixed_array()); + // Copy the JS object part. + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { + __ mov(ebx, FieldOperand(edi, i)); + __ mov(FieldOperand(eax, i), ebx); + } // Get the length (smi tagged) and set that as an in-object property too. STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); __ mov(ecx, Operand(esp, 1 * kPointerSize)); - __ AssertSmi(ecx); __ mov(FieldOperand(eax, JSObject::kHeaderSize + Heap::kArgumentsLengthIndex * kPointerSize), ecx); diff --git a/src/objects.cc b/src/objects.cc index 3d5987c3df..ab34acf880 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1834,6 +1834,7 @@ void JSObject::AddFastProperty(Handle object, Handle value, PropertyAttributes attributes, StoreFromKeyed store_mode, + ValueType value_type, TransitionFlag flag) { ASSERT(!object->IsJSGlobalProxy()); @@ -1843,7 +1844,7 @@ void JSObject::AddFastProperty(Handle object, handle(object->map()), name, value, attributes, flag); } else if (!object->TooManyFastProperties(store_mode)) { Isolate* isolate = object->GetIsolate(); - Representation representation = value->OptimalRepresentation(); + Representation representation = value->OptimalRepresentation(value_type); maybe_map = Map::CopyWithField( handle(object->map(), isolate), name, value->OptimalType(isolate, representation), @@ -1900,6 +1901,7 @@ MaybeHandle JSObject::AddPropertyInternal( StrictMode strict_mode, JSReceiver::StoreFromKeyed store_mode, ExtensibilityCheck extensibility_check, + ValueType value_type, StoreMode mode, TransitionFlag transition_flag) { ASSERT(!object->IsJSGlobalProxy()); @@ -1924,7 +1926,7 @@ MaybeHandle JSObject::AddPropertyInternal( if (object->HasFastProperties()) { AddFastProperty(object, name, value, attributes, store_mode, - transition_flag); + value_type, transition_flag); } if (!object->HasFastProperties()) { @@ -3974,7 +3976,8 @@ MaybeHandle JSObject::SetPropertyUsingTransition( return JSObject::AddPropertyInternal( object, name, value, attributes, SLOPPY, JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, - JSReceiver::OMIT_EXTENSIBILITY_CHECK, FORCE_FIELD, OMIT_TRANSITION); + JSReceiver::OMIT_EXTENSIBILITY_CHECK, + JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); } // Keep the target CONSTANT if the same value is stored. @@ -4220,6 +4223,7 @@ void JSObject::AddProperty( Handle name, Handle value, PropertyAttributes attributes, + ValueType value_type, StoreMode store_mode) { #ifdef DEBUG uint32_t index; @@ -4230,8 +4234,9 @@ void JSObject::AddProperty( ASSERT(!it.IsFound()); ASSERT(object->map()->is_extensible()); #endif - SetOwnPropertyIgnoreAttributes(object, name, value, attributes, store_mode, - OMIT_EXTENSIBILITY_CHECK).Check(); + SetOwnPropertyIgnoreAttributes( + object, name, value, attributes, value_type, store_mode, + OMIT_EXTENSIBILITY_CHECK).Check(); } @@ -4246,6 +4251,7 @@ MaybeHandle JSObject::SetOwnPropertyIgnoreAttributes( Handle name, Handle value, PropertyAttributes attributes, + ValueType value_type, StoreMode mode, ExtensibilityCheck extensibility_check, StoreFromKeyed store_from_keyed, @@ -4274,9 +4280,8 @@ MaybeHandle JSObject::SetOwnPropertyIgnoreAttributes( Handle proto(object->GetPrototype(), isolate); if (proto->IsNull()) return value; ASSERT(proto->IsJSGlobalObject()); - return SetOwnPropertyIgnoreAttributes(Handle::cast(proto), name, - value, attributes, mode, - extensibility_check); + return SetOwnPropertyIgnoreAttributes(Handle::cast(proto), + name, value, attributes, value_type, mode, extensibility_check); } if (lookup.IsInterceptor() || @@ -4291,8 +4296,7 @@ MaybeHandle JSObject::SetOwnPropertyIgnoreAttributes( ? OMIT_TRANSITION : INSERT_TRANSITION; // Neither properties nor transitions found. return AddPropertyInternal(object, name, value, attributes, SLOPPY, - store_from_keyed, extensibility_check, mode, - flag); + store_from_keyed, extensibility_check, value_type, mode, flag); } Handle old_value = isolate->factory()->the_hole_value(); @@ -5256,8 +5260,12 @@ Handle JSObject::SetHiddenPropertiesHashTable(Handle object, } } - SetOwnPropertyIgnoreAttributes(object, isolate->factory()->hidden_string(), - value, DONT_ENUM, ALLOW_AS_CONSTANT, + SetOwnPropertyIgnoreAttributes(object, + isolate->factory()->hidden_string(), + value, + DONT_ENUM, + OPTIMAL_REPRESENTATION, + ALLOW_AS_CONSTANT, OMIT_EXTENSIBILITY_CHECK).Assert(); return object; } @@ -5602,10 +5610,11 @@ bool JSObject::ReferencesObject(Object* obj) { // For functions check the context. if (IsJSFunction()) { // Get the constructor function for arguments array. - Map* arguments_map = - heap->isolate()->context()->native_context()->sloppy_arguments_map(); + JSObject* arguments_boilerplate = + heap->isolate()->context()->native_context()-> + sloppy_arguments_boilerplate(); JSFunction* arguments_function = - JSFunction::cast(arguments_map->constructor()); + JSFunction::cast(arguments_boilerplate->map()->constructor()); // Get the context and don't check if it is the native context. JSFunction* f = JSFunction::cast(this); @@ -5897,7 +5906,7 @@ MaybeHandle JSObjectWalkVisitor::StructureWalk( Handle object) { Isolate* isolate = this->isolate(); bool copying = this->copying(); - bool shallow = hints_ == JSObject::kObjectIsShallow; + bool shallow = hints_ == JSObject::kObjectIsShallowArray; if (!shallow) { StackLimitCheck check(isolate); @@ -6384,8 +6393,12 @@ MaybeHandle JSReceiver::GetKeys(Handle object, USE(ContainsOnlyValidKeys); Isolate* isolate = object->GetIsolate(); Handle content = isolate->factory()->empty_fixed_array(); - Handle arguments_function( - JSFunction::cast(isolate->sloppy_arguments_map()->constructor())); + Handle arguments_boilerplate = Handle( + isolate->context()->native_context()->sloppy_arguments_boilerplate(), + isolate); + Handle arguments_function = Handle( + JSFunction::cast(arguments_boilerplate->map()->constructor()), + isolate); // Only collect keys if access is permitted. for (Handle p = object; diff --git a/src/objects.h b/src/objects.h index d49e365e59..e2d9791ddb 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1406,8 +1406,17 @@ class Object { bool ToInt32(int32_t* value); bool ToUint32(uint32_t* value); - inline Representation OptimalRepresentation() { + // Indicates whether OptimalRepresentation can do its work, or whether it + // always has to return Representation::Tagged(). + enum ValueType { + OPTIMAL_REPRESENTATION, + FORCE_TAGGED + }; + + inline Representation OptimalRepresentation( + ValueType type = OPTIMAL_REPRESENTATION) { if (!FLAG_track_fields) return Representation::Tagged(); + if (type == FORCE_TAGGED) return Representation::Tagged(); if (IsSmi()) { return Representation::Smi(); } else if (FLAG_track_double_fields && IsHeapNumber()) { @@ -2158,6 +2167,7 @@ class JSObject: public JSReceiver { Handle key, Handle value, PropertyAttributes attributes, + ValueType value_type = OPTIMAL_REPRESENTATION, StoreMode mode = ALLOW_AS_CONSTANT, ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK, StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, @@ -2167,6 +2177,7 @@ class JSObject: public JSReceiver { Handle key, Handle value, PropertyAttributes attributes, + ValueType value_type = OPTIMAL_REPRESENTATION, StoreMode mode = ALLOW_AS_CONSTANT); // Extend the receiver with a single fast property appeared first in the @@ -2506,7 +2517,10 @@ class JSObject: public JSReceiver { static void SetObserved(Handle object); // Copy object. - enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 }; + enum DeepCopyHints { + kNoHints = 0, + kObjectIsShallowArray = 1 + }; static Handle Copy(Handle object); MUST_USE_RESULT static MaybeHandle DeepCopy( @@ -2771,6 +2785,7 @@ class JSObject: public JSReceiver { StrictMode strict_mode, StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK, + ValueType value_type = OPTIMAL_REPRESENTATION, StoreMode mode = ALLOW_AS_CONSTANT, TransitionFlag flag = INSERT_TRANSITION); @@ -2780,6 +2795,7 @@ class JSObject: public JSReceiver { Handle value, PropertyAttributes attributes, StoreFromKeyed store_mode, + ValueType value_type, TransitionFlag flag); // Add a property to a slow-case object. diff --git a/src/runtime.cc b/src/runtime.cc index 893e31be5c..d860245815 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -251,6 +251,9 @@ MUST_USE_RESULT static MaybeHandle CreateObjectLiteralBoilerplate( JSObject::NormalizeProperties( boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2); } + Object::ValueType value_type = should_normalize + ? Object::FORCE_TAGGED : Object::OPTIMAL_REPRESENTATION; + // TODO(verwaest): Support tracking representations in the boilerplate. for (int index = 0; index < length; index +=2) { Handle key(constant_properties->get(index+0), isolate); @@ -280,7 +283,8 @@ MUST_USE_RESULT static MaybeHandle CreateObjectLiteralBoilerplate( Handle name(String::cast(*key)); ASSERT(!name->AsArrayIndex(&element_index)); maybe_result = JSObject::SetOwnPropertyIgnoreAttributes( - boilerplate, name, value, NONE, mode); + boilerplate, name, value, NONE, + value_type, mode); } } else if (key->ToArrayIndex(&element_index)) { // Array index (uint32). @@ -299,7 +303,7 @@ MUST_USE_RESULT static MaybeHandle CreateObjectLiteralBoilerplate( const char* str = DoubleToCString(num, buffer); Handle name = isolate->factory()->NewStringFromAsciiChecked(str); maybe_result = JSObject::SetOwnPropertyIgnoreAttributes( - boilerplate, name, value, NONE, mode); + boilerplate, name, value, NONE, value_type, mode); } // If setting the property on the boilerplate throws an // exception, the exception is converted to an empty handle in @@ -568,8 +572,8 @@ static MaybeHandle CreateArrayLiteralImpl(Isolate* isolate, AllocationSiteUsageContext usage_context(isolate, site, enable_mementos); usage_context.EnterNewScope(); JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0 - ? JSObject::kNoHints - : JSObject::kObjectIsShallow; + ? JSObject::kNoHints + : JSObject::kObjectIsShallowArray; MaybeHandle copy = JSObject::DeepCopy(boilerplate, &usage_context, hints); usage_context.ExitScope(site, boilerplate); @@ -5089,6 +5093,7 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) { isolate, result, JSObject::SetOwnPropertyIgnoreAttributes( js_object, name, obj_value, attr, + Object::OPTIMAL_REPRESENTATION, ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK, JSReceiver::MAY_BE_STORE_FROM_KEYED, @@ -5244,8 +5249,9 @@ MaybeHandle Runtime::DefineObjectProperty( } else { if (name->IsString()) name = String::Flatten(Handle::cast(name)); return JSObject::SetOwnPropertyIgnoreAttributes( - js_object, name, value, attr, ALLOW_AS_CONSTANT, - JSReceiver::PERFORM_EXTENSIBILITY_CHECK, store_from_keyed); + js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION, + ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK, + store_from_keyed); } } @@ -5260,8 +5266,9 @@ MaybeHandle Runtime::DefineObjectProperty( SLOPPY, false, DEFINE_PROPERTY); } else { return JSObject::SetOwnPropertyIgnoreAttributes( - js_object, name, value, attr, ALLOW_AS_CONSTANT, - JSReceiver::PERFORM_EXTENSIBILITY_CHECK, store_from_keyed); + js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION, + ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK, + store_from_keyed); } } @@ -13093,8 +13100,10 @@ RUNTIME_FUNCTION(Runtime_DebugReferencedBy) { // Get the constructor function for context extension and arguments array. + Handle arguments_boilerplate( + isolate->sloppy_arguments_boilerplate()); Handle arguments_function( - JSFunction::cast(isolate->sloppy_arguments_map()->constructor())); + JSFunction::cast(arguments_boilerplate->map()->constructor())); // Get the number of referencing objects. int count; diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 63b1b8fcc8..c08e38b509 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -922,35 +922,35 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { // rax = address of new object(s) (tagged) // rcx = argument count (untagged) - // Get the arguments map from the current native context into rdi. - Label has_mapped_parameters, instantiate; + // Get the arguments boilerplate from the current native context into rdi. + Label has_mapped_parameters, copy; __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); __ testp(rbx, rbx); __ j(not_zero, &has_mapped_parameters, Label::kNear); - const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX; + const int kIndex = Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX; __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex))); - __ jmp(&instantiate, Label::kNear); + __ jmp(©, Label::kNear); - const int kAliasedIndex = Context::ALIASED_ARGUMENTS_MAP_INDEX; + const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX; __ bind(&has_mapped_parameters); __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex))); - __ bind(&instantiate); + __ bind(©); // rax = address of new object (tagged) // rbx = mapped parameter count (untagged) // rcx = argument count (untagged) - // rdi = address of arguments map (tagged) - __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); - __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); - __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); - __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); + // rdi = address of boilerplate object (tagged) + // Copy the JS object part. + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { + __ movp(rdx, FieldOperand(rdi, i)); + __ movp(FieldOperand(rax, i), rdx); + } // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ movp(rdx, args.GetArgumentOperand(0)); - __ AssertNotSmi(rdx); __ movp(FieldOperand(rax, JSObject::kHeaderSize + Heap::kArgumentsCalleeIndex * kPointerSize), rdx); @@ -1140,16 +1140,18 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Do the allocation of both objects in one go. __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); - // Get the arguments map from the current native context. + // Get the arguments boilerplate from the current native context. __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); - const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX); + const int offset = + Context::SlotOffset(Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX); __ movp(rdi, Operand(rdi, offset)); - __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); - __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); - __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); - __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); + // Copy the JS object part. + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { + __ movp(rbx, FieldOperand(rdi, i)); + __ movp(FieldOperand(rax, i), rbx); + } // Get the length (smi tagged) and set that as an in-object property too. STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h index e1676e5e6f..1fadfb7535 100644 --- a/test/cctest/cctest.h +++ b/test/cctest/cctest.h @@ -83,6 +83,7 @@ typedef v8::internal::EnumSet CcTestExtensionFlags; // Use this to expose protected methods in i::Heap. class TestHeap : public i::Heap { public: + using i::Heap::AllocateArgumentsObject; using i::Heap::AllocateByteArray; using i::Heap::AllocateFixedArray; using i::Heap::AllocateHeapNumber; diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc index f26c4615a7..f80e6a5a7f 100644 --- a/test/cctest/test-alloc.cc +++ b/test/cctest/test-alloc.cc @@ -50,6 +50,7 @@ static AllocationResult AllocateAfterFailures() { // for specific kinds. heap->AllocateFixedArray(100).ToObjectChecked(); heap->AllocateHeapNumber(0.42).ToObjectChecked(); + heap->AllocateArgumentsObject(Smi::FromInt(87), 10).ToObjectChecked(); Object* object = heap->AllocateJSObject( *CcTest::i_isolate()->object_function()).ToObjectChecked(); heap->CopyJSObject(JSObject::cast(object)).ToObjectChecked();