From d07de6ed592718359034fd9a1f50cdaa996b9756 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Wed, 30 Jul 2014 10:09:10 +0000 Subject: [PATCH] Encapsulate type in the PropertyHandlerCompiler BUG= R=ishell@chromium.org Review URL: https://codereview.chromium.org/426633002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22700 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/stub-cache-arm.cc | 53 +++++++++--------- src/arm64/stub-cache-arm64.cc | 53 +++++++++--------- src/ia32/stub-cache-ia32.cc | 56 +++++++++---------- src/ic.cc | 33 ++++++----- src/objects-inl.h | 7 ++- src/objects.cc | 23 ++++++-- src/objects.h | 6 ++ src/stub-cache.cc | 126 ++++++++++++++++++++---------------------- src/stub-cache.h | 99 ++++++++++++++------------------- src/x64/stub-cache-x64.cc | 58 +++++++++---------- 10 files changed, 253 insertions(+), 261 deletions(-) diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 391d85a..ea1ed1b 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -733,10 +733,10 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, Register PropertyHandlerCompiler::CheckPrototypes( - Handle type, Register object_reg, Handle holder, - Register holder_reg, Register scratch1, Register scratch2, - Handle name, Label* miss, PrototypeCheckType check) { - Handle receiver_map(IC::TypeToMap(*type, isolate())); + Register object_reg, Handle holder, Register holder_reg, + Register scratch1, Register scratch2, Handle name, Label* miss, + PrototypeCheckType check) { + Handle receiver_map(IC::TypeToMap(*type(), isolate())); // Make sure there's no overlap between holder and object registers. ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); @@ -748,8 +748,8 @@ Register PropertyHandlerCompiler::CheckPrototypes( int depth = 0; Handle current = Handle::null(); - if (type->IsConstant()) { - current = Handle::cast(type->AsConstant()->Value()); + if (type()->IsConstant()) { + current = Handle::cast(type()->AsConstant()->Value()); } Handle prototype = Handle::null(); Handle current_map = receiver_map; @@ -864,14 +864,13 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle name, Label* miss) { } -Register NamedLoadHandlerCompiler::CallbackFrontend(Handle type, - Register object_reg, +Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Handle holder, Handle name, Handle callback) { Label miss; - Register reg = FrontendHeader(type, object_reg, holder, name, &miss); + Register reg = FrontendHeader(object_reg, holder, name, &miss); if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { ASSERT(!reg.is(scratch2())); @@ -972,9 +971,8 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( void NamedLoadHandlerCompiler::GenerateLoadInterceptor( - Register holder_reg, Handle object, - Handle interceptor_holder, LookupResult* lookup, - Handle name) { + Register holder_reg, Handle interceptor_holder, + LookupResult* lookup, Handle name) { ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); @@ -987,10 +985,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( compile_followup_inline = true; } else if (lookup->type() == CALLBACKS && lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { - ExecutableAccessorInfo* callback = - ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); - compile_followup_inline = callback->getter() != NULL && - callback->IsCompatibleReceiver(*object); + Handle callback( + ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); + compile_followup_inline = + callback->getter() != NULL && + ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, + type()); } } @@ -1061,8 +1061,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( Handle NamedStoreHandlerCompiler::CompileStoreCallback( Handle object, Handle holder, Handle name, Handle callback) { - Register holder_reg = - Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); + Register holder_reg = Frontend(receiver(), holder, name); // Stub never generated for non-global objects that require access checks. ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); @@ -1147,8 +1146,8 @@ Handle NamedStoreHandlerCompiler::CompileStoreInterceptor( Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle type, Handle last, Handle name) { - NonexistentFrontend(type, last, name); + Handle last, Handle name) { + NonexistentFrontend(last, name); // Return undefined if maps of the full prototype chain are still the // same and no global property with this name contains a value. @@ -1236,25 +1235,25 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( Handle NamedLoadHandlerCompiler::CompileLoadGlobal( - Handle type, Handle global, - Handle cell, Handle name, bool is_dont_delete) { + Handle global, Handle cell, Handle name, + bool is_dont_delete) { Label miss; - FrontendHeader(type, receiver(), global, name, &miss); + FrontendHeader(receiver(), global, name, &miss); // Get the value from the cell. - __ mov(r3, Operand(cell)); - __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); + Register result = StoreIC::ValueRegister(); + __ mov(result, Operand(cell)); + __ ldr(result, FieldMemOperand(result, Cell::kValueOffset)); // Check for deleted property if property can actually be deleted. if (!is_dont_delete) { __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ cmp(r4, ip); + __ cmp(result, ip); __ b(eq, &miss); } Counters* counters = isolate()->counters(); __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); - __ mov(r0, r4); __ Ret(); FrontendFooter(name, &miss); diff --git a/src/arm64/stub-cache-arm64.cc b/src/arm64/stub-cache-arm64.cc index c1ae0eb..20431d6 100644 --- a/src/arm64/stub-cache-arm64.cc +++ b/src/arm64/stub-cache-arm64.cc @@ -682,10 +682,10 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, Register PropertyHandlerCompiler::CheckPrototypes( - Handle type, Register object_reg, Handle holder, - Register holder_reg, Register scratch1, Register scratch2, - Handle name, Label* miss, PrototypeCheckType check) { - Handle receiver_map(IC::TypeToMap(*type, isolate())); + Register object_reg, Handle holder, Register holder_reg, + Register scratch1, Register scratch2, Handle name, Label* miss, + PrototypeCheckType check) { + Handle receiver_map(IC::TypeToMap(*type(), isolate())); // object_reg and holder_reg registers can alias. ASSERT(!AreAliased(object_reg, scratch1, scratch2)); @@ -696,8 +696,8 @@ Register PropertyHandlerCompiler::CheckPrototypes( int depth = 0; Handle current = Handle::null(); - if (type->IsConstant()) { - current = Handle::cast(type->AsConstant()->Value()); + if (type()->IsConstant()) { + current = Handle::cast(type()->AsConstant()->Value()); } Handle prototype = Handle::null(); Handle current_map = receiver_map; @@ -817,14 +817,13 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle name, Label* miss) { } -Register NamedLoadHandlerCompiler::CallbackFrontend(Handle type, - Register object_reg, +Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Handle holder, Handle name, Handle callback) { Label miss; - Register reg = FrontendHeader(type, object_reg, holder, name, &miss); + Register reg = FrontendHeader(object_reg, holder, name, &miss); // FrontendHeader can return its result into scratch1() so do not // use it. Register scratch2 = this->scratch2(); @@ -934,9 +933,8 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( void NamedLoadHandlerCompiler::GenerateLoadInterceptor( - Register holder_reg, Handle object, - Handle interceptor_holder, LookupResult* lookup, - Handle name) { + Register holder_reg, Handle interceptor_holder, + LookupResult* lookup, Handle name) { ASSERT(!AreAliased(receiver(), this->name(), scratch1(), scratch2(), scratch3())); ASSERT(interceptor_holder->HasNamedInterceptor()); @@ -950,10 +948,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( compile_followup_inline = true; } else if (lookup->type() == CALLBACKS && lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { - ExecutableAccessorInfo* callback = - ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); - compile_followup_inline = callback->getter() != NULL && - callback->IsCompatibleReceiver(*object); + Handle callback( + ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); + compile_followup_inline = + callback->getter() != NULL && + ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, + type()); } } @@ -1024,8 +1024,7 @@ Handle NamedStoreHandlerCompiler::CompileStoreCallback( Handle object, Handle holder, Handle name, Handle callback) { ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); - Register holder_reg = - Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); + Register holder_reg = Frontend(receiver(), holder, name); // Stub never generated for non-global objects that require access checks. ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); @@ -1116,8 +1115,8 @@ Handle NamedStoreHandlerCompiler::CompileStoreInterceptor( Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle type, Handle last, Handle name) { - NonexistentFrontend(type, last, name); + Handle last, Handle name) { + NonexistentFrontend(last, name); // Return undefined if maps of the full prototype chain are still the // same and no global property with this name contains a value. @@ -1206,23 +1205,23 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( Handle NamedLoadHandlerCompiler::CompileLoadGlobal( - Handle type, Handle global, - Handle cell, Handle name, bool is_dont_delete) { + Handle global, Handle cell, Handle name, + bool is_dont_delete) { Label miss; - FrontendHeader(type, receiver(), global, name, &miss); + FrontendHeader(receiver(), global, name, &miss); // Get the value from the cell. - __ Mov(x3, Operand(cell)); - __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); + Register result = StoreIC::ValueRegister(); + __ Mov(result, Operand(cell)); + __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); // Check for deleted property if property can actually be deleted. if (!is_dont_delete) { - __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); + __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); } Counters* counters = isolate()->counters(); __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); - __ Mov(x0, x4); __ Ret(); FrontendFooter(name, &miss); diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 8192ece..b5aaa12 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -693,10 +693,10 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, Register PropertyHandlerCompiler::CheckPrototypes( - Handle type, Register object_reg, Handle holder, - Register holder_reg, Register scratch1, Register scratch2, - Handle name, Label* miss, PrototypeCheckType check) { - Handle receiver_map(IC::TypeToMap(*type, isolate())); + Register object_reg, Handle holder, Register holder_reg, + Register scratch1, Register scratch2, Handle name, Label* miss, + PrototypeCheckType check) { + Handle receiver_map(IC::TypeToMap(*type(), isolate())); // Make sure there's no overlap between holder and object registers. ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); @@ -708,8 +708,8 @@ Register PropertyHandlerCompiler::CheckPrototypes( int depth = 0; Handle current = Handle::null(); - if (type->IsConstant()) current = - Handle::cast(type->AsConstant()->Value()); + if (type()->IsConstant()) + current = Handle::cast(type()->AsConstant()->Value()); Handle prototype = Handle::null(); Handle current_map = receiver_map; Handle holder_map(holder->map()); @@ -824,14 +824,13 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle name, Label* miss) { } -Register NamedLoadHandlerCompiler::CallbackFrontend(Handle type, - Register object_reg, +Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Handle holder, Handle name, Handle callback) { Label miss; - Register reg = FrontendHeader(type, object_reg, holder, name, &miss); + Register reg = FrontendHeader(object_reg, holder, name, &miss); if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { ASSERT(!reg.is(scratch2())); @@ -944,9 +943,8 @@ void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle value) { void NamedLoadHandlerCompiler::GenerateLoadInterceptor( - Register holder_reg, Handle object, - Handle interceptor_holder, LookupResult* lookup, - Handle name) { + Register holder_reg, Handle interceptor_holder, + LookupResult* lookup, Handle name) { ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); @@ -959,10 +957,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( compile_followup_inline = true; } else if (lookup->type() == CALLBACKS && lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { - ExecutableAccessorInfo* callback = - ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); - compile_followup_inline = callback->getter() != NULL && - callback->IsCompatibleReceiver(*object); + Handle callback( + ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); + compile_followup_inline = + callback->getter() != NULL && + ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, + type()); } } @@ -1044,8 +1044,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( Handle NamedStoreHandlerCompiler::CompileStoreCallback( Handle object, Handle holder, Handle name, Handle callback) { - Register holder_reg = - Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); + Register holder_reg = Frontend(receiver(), holder, name); __ pop(scratch1()); // remove the return address __ push(receiver()); @@ -1173,8 +1172,8 @@ Handle PropertyICCompiler::CompileKeyedStorePolymorphic( Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle type, Handle last, Handle name) { - NonexistentFrontend(type, last, name); + Handle last, Handle name) { + NonexistentFrontend(last, name); // Return undefined if maps of the full prototype chain are still the // same and no global property with this name contains a value. @@ -1257,25 +1256,26 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( Handle NamedLoadHandlerCompiler::CompileLoadGlobal( - Handle type, Handle global, - Handle cell, Handle name, bool is_dont_delete) { + Handle global, Handle cell, Handle name, + bool is_dont_delete) { Label miss; - FrontendHeader(type, receiver(), global, name, &miss); + FrontendHeader(receiver(), global, name, &miss); // Get the value from the cell. + Register result = StoreIC::ValueRegister(); if (masm()->serializer_enabled()) { - __ mov(eax, Immediate(cell)); - __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); + __ mov(result, Immediate(cell)); + __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); } else { - __ mov(eax, Operand::ForCell(cell)); + __ mov(result, Operand::ForCell(cell)); } // Check for deleted property if property can actually be deleted. if (!is_dont_delete) { - __ cmp(eax, factory()->the_hole_value()); + __ cmp(result, factory()->the_hole_value()); __ j(equal, &miss); } else if (FLAG_debug_code) { - __ cmp(eax, factory()->the_hole_value()); + __ cmp(result, factory()->the_hole_value()); __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); } diff --git a/src/ic.cc b/src/ic.cc index c11f582..eb84fd1 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -942,7 +942,7 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle object, Handle type = receiver_type(); Handle holder(lookup->holder()); bool receiver_is_holder = object.is_identical_to(holder); - NamedLoadHandlerCompiler compiler(isolate(), cache_holder); + NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), cache_holder); switch (lookup->type()) { case FIELD: { @@ -950,12 +950,12 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle object, if (receiver_is_holder) { return SimpleFieldLoad(field); } - return compiler.CompileLoadField( - type, holder, name, field, lookup->representation()); + return compiler.CompileLoadField(holder, name, field, + lookup->representation()); } case CONSTANT: { Handle constant(lookup->GetConstant(), isolate()); - return compiler.CompileLoadConstant(type, holder, name, constant); + return compiler.CompileLoadConstant(holder, name, constant); } case NORMAL: if (kind() != Code::LOAD_IC) break; @@ -963,8 +963,8 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle object, Handle global = Handle::cast(holder); Handle cell( global->GetPropertyCell(lookup), isolate()); - Handle code = compiler.CompileLoadGlobal( - type, global, cell, name, lookup->IsDontDelete()); + Handle code = compiler.CompileLoadGlobal(global, cell, name, + lookup->IsDontDelete()); // TODO(verwaest): Move caching of these NORMAL stubs outside as well. CacheHolderFlag flag; Handle stub_holder_map = @@ -997,8 +997,11 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle object, Handle info = Handle::cast(callback); if (v8::ToCData
(info->getter()) == 0) break; - if (!info->IsCompatibleReceiver(*object)) break; - return compiler.CompileLoadCallback(type, holder, name, info); + if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, + type)) { + break; + } + return compiler.CompileLoadCallback(holder, name, info); } else if (callback->IsAccessorPair()) { Handle getter(Handle::cast(callback)->getter(), isolate()); @@ -1016,10 +1019,9 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle object, CallOptimization call_optimization(function); if (call_optimization.is_simple_api_call() && call_optimization.IsCompatibleReceiver(object, holder)) { - return compiler.CompileLoadCallback( - type, holder, name, call_optimization); + return compiler.CompileLoadCallback(holder, name, call_optimization); } - return compiler.CompileLoadViaGetter(type, holder, name, function); + return compiler.CompileLoadViaGetter(holder, name, function); } // TODO(dcarney): Handle correctly. ASSERT(callback->IsDeclaredAccessorInfo()); @@ -1027,7 +1029,7 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle object, } case INTERCEPTOR: ASSERT(HasInterceptorGetter(*holder)); - return compiler.CompileLoadInterceptor(type, holder, name); + return compiler.CompileLoadInterceptor(holder, name); default: break; } @@ -1392,7 +1394,7 @@ Handle StoreIC::CompileHandler(LookupResult* lookup, Handle receiver = Handle::cast(object); Handle holder(lookup->holder()); - NamedStoreHandlerCompiler compiler(isolate()); + NamedStoreHandlerCompiler compiler(isolate(), receiver_type()); if (lookup->IsTransition()) { // Explicitly pass in the receiver map since LookupForWrite may have @@ -1438,7 +1440,10 @@ Handle StoreIC::CompileHandler(LookupResult* lookup, Handle::cast(callback); if (v8::ToCData
(info->setter()) == 0) break; if (!holder->HasFastProperties()) break; - if (!info->IsCompatibleReceiver(*receiver)) break; + if (!ExecutableAccessorInfo::IsCompatibleReceiverType( + isolate(), info, receiver_type())) { + break; + } return compiler.CompileStoreCallback(receiver, holder, name, info); } else if (callback->IsAccessorPair()) { Handle setter( diff --git a/src/objects-inl.h b/src/objects-inl.h index 22bdfa3..e14c1af 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -6771,9 +6771,10 @@ void AccessorInfo::set_property_attributes(PropertyAttributes attributes) { bool AccessorInfo::IsCompatibleReceiver(Object* receiver) { - Object* function_template = expected_receiver_type(); - if (!function_template->IsFunctionTemplateInfo()) return true; - return FunctionTemplateInfo::cast(function_template)->IsTemplateFor(receiver); + if (!HasExpectedReceiverType()) return true; + if (!receiver->IsJSObject()) return false; + return FunctionTemplateInfo::cast(expected_receiver_type()) + ->IsTemplateFor(JSObject::cast(receiver)->map()); } diff --git a/src/objects.cc b/src/objects.cc index a846fba..79b2ffc 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -409,8 +409,8 @@ MaybeHandle Object::GetPropertyWithAccessor(Handle receiver, ASSERT(!structure->IsForeign()); // api style callbacks. if (structure->IsAccessorInfo()) { - Handle accessor_info = Handle::cast(structure); - if (!accessor_info->IsCompatibleReceiver(*receiver)) { + Handle info = Handle::cast(structure); + if (!info->IsCompatibleReceiver(*receiver)) { Handle args[2] = { name, receiver }; Handle error = isolate->factory()->NewTypeError("incompatible_method_receiver", @@ -462,6 +462,17 @@ MaybeHandle Object::GetPropertyWithAccessor(Handle receiver, } +bool AccessorInfo::IsCompatibleReceiverType(Isolate* isolate, + Handle info, + Handle type) { + if (!info->HasExpectedReceiverType()) return true; + Handle map = IC::TypeToMap(*type, isolate); + if (!map->IsJSObjectMap()) return false; + return FunctionTemplateInfo::cast(info->expected_receiver_type()) + ->IsTemplateFor(*map); +} + + MaybeHandle Object::SetPropertyWithAccessor( Handle receiver, Handle name, Handle value, Handle holder, Handle structure, StrictMode strict_mode) { @@ -474,8 +485,8 @@ MaybeHandle Object::SetPropertyWithAccessor( // Don't call executable accessor setters with non-JSObject receivers. if (!receiver->IsJSObject()) return value; // api style callbacks - ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure); - if (!data->IsCompatibleReceiver(*receiver)) { + ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure); + if (!info->IsCompatibleReceiver(*receiver)) { Handle args[2] = { name, receiver }; Handle error = isolate->factory()->NewTypeError("incompatible_method_receiver", @@ -485,13 +496,13 @@ MaybeHandle Object::SetPropertyWithAccessor( } // TODO(rossberg): Support symbols in the API. if (name->IsSymbol()) return value; - Object* call_obj = data->setter(); + Object* call_obj = info->setter(); v8::AccessorSetterCallback call_fun = v8::ToCData(call_obj); if (call_fun == NULL) return value; Handle key = Handle::cast(name); LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); - PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder); + PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); args.Call(call_fun, v8::Utils::ToLocal(key), v8::Utils::ToLocal(value)); diff --git a/src/objects.h b/src/objects.h index 8b6e00a..1c0fa64 100644 --- a/src/objects.h +++ b/src/objects.h @@ -10528,6 +10528,9 @@ class AccessorInfo: public Struct { inline void set_property_attributes(PropertyAttributes attributes); // Checks whether the given receiver is compatible with this accessor. + static bool IsCompatibleReceiverType(Isolate* isolate, + Handle info, + Handle type); inline bool IsCompatibleReceiver(Object* receiver); DECLARE_CAST(AccessorInfo) @@ -10547,6 +10550,9 @@ class AccessorInfo: public Struct { static const int kSize = kExpectedReceiverTypeOffset + kPointerSize; private: + inline bool HasExpectedReceiverType() { + return expected_receiver_type()->IsFunctionTemplateInfo(); + } // Bit positions in flag. static const int kAllCanReadBit = 0; static const int kAllCanWriteBit = 1; diff --git a/src/stub-cache.cc b/src/stub-cache.cc index eb71952..3173f4d 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -203,8 +203,8 @@ Handle NamedLoadHandlerCompiler::ComputeLoadNonexistent( cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); if (!handler.is_null()) return handler; - NamedLoadHandlerCompiler compiler(isolate, flag); - handler = compiler.CompileLoadNonexistent(type, last, cache_name); + NamedLoadHandlerCompiler compiler(isolate, type, flag); + handler = compiler.CompileLoadNonexistent(last, cache_name); Map::UpdateCodeCache(stub_holder_map, cache_name, handler); return handler; } @@ -497,25 +497,27 @@ void StubCache::CollectMatchingMaps(SmallMapList* types, RUNTIME_FUNCTION(StoreCallbackProperty) { - JSObject* receiver = JSObject::cast(args[0]); - JSObject* holder = JSObject::cast(args[1]); - ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[2]); + Handle receiver = args.at(0); + Handle holder = args.at(1); + Handle callback = args.at(2); + Handle name = args.at(3); + Handle value = args.at(4); + HandleScope scope(isolate); + + ASSERT(callback->IsCompatibleReceiver(*receiver)); + Address setter_address = v8::ToCData
(callback->setter()); v8::AccessorSetterCallback fun = FUNCTION_CAST(setter_address); ASSERT(fun != NULL); - ASSERT(callback->IsCompatibleReceiver(receiver)); - Handle name = args.at(3); - Handle value = args.at(4); - HandleScope scope(isolate); // TODO(rossberg): Support symbols in the API. if (name->IsSymbol()) return *value; Handle str = Handle::cast(name); - LOG(isolate, ApiNamedPropertyAccess("store", receiver, *name)); - PropertyCallbackArguments - custom_args(isolate, callback->data(), receiver, holder); + LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name)); + PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver, + *holder); custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value)); RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); return *value; @@ -746,20 +748,19 @@ Handle PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, #define __ ACCESS_MASM(masm()) -Register NamedLoadHandlerCompiler::FrontendHeader(Handle type, - Register object_reg, +Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, Handle holder, Handle name, Label* miss) { PrototypeCheckType check_type = CHECK_ALL_MAPS; int function_index = -1; - if (type->Is(HeapType::String())) { + if (type()->Is(HeapType::String())) { function_index = Context::STRING_FUNCTION_INDEX; - } else if (type->Is(HeapType::Symbol())) { + } else if (type()->Is(HeapType::Symbol())) { function_index = Context::SYMBOL_FUNCTION_INDEX; - } else if (type->Is(HeapType::Number())) { + } else if (type()->Is(HeapType::Number())) { function_index = Context::NUMBER_FUNCTION_INDEX; - } else if (type->Is(HeapType::Boolean())) { + } else if (type()->Is(HeapType::Boolean())) { function_index = Context::BOOLEAN_FUNCTION_INDEX; } else { check_type = SKIP_RECEIVER; @@ -770,26 +771,24 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Handle type, masm(), function_index, scratch1(), miss); Object* function = isolate()->native_context()->get(function_index); Object* prototype = JSFunction::cast(function)->instance_prototype(); - type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate()); + set_type_for_object(handle(prototype, isolate())); object_reg = scratch1(); } // Check that the maps starting from the prototype haven't changed. - return CheckPrototypes( - type, object_reg, holder, scratch1(), scratch2(), scratch3(), - name, miss, check_type); + return CheckPrototypes(object_reg, holder, scratch1(), scratch2(), scratch3(), + name, miss, check_type); } // Frontend for store uses the name register. It has to be restored before a // miss. -Register NamedStoreHandlerCompiler::FrontendHeader(Handle type, - Register object_reg, +Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, Handle holder, Handle name, Label* miss) { - return CheckPrototypes(type, object_reg, holder, this->name(), - scratch1(), scratch2(), name, miss, SKIP_RECEIVER); + return CheckPrototypes(object_reg, holder, this->name(), scratch1(), + scratch2(), name, miss, SKIP_RECEIVER); } @@ -801,19 +800,17 @@ bool PropertyICCompiler::IncludesNumberType(TypeHandleList* types) { } -Register PropertyHandlerCompiler::Frontend(Handle type, - Register object_reg, +Register PropertyHandlerCompiler::Frontend(Register object_reg, Handle holder, Handle name) { Label miss; - Register reg = FrontendHeader(type, object_reg, holder, name, &miss); + Register reg = FrontendHeader(object_reg, holder, name, &miss); FrontendFooter(name, &miss); return reg; } -void NamedLoadHandlerCompiler::NonexistentFrontend(Handle type, - Handle last, +void NamedLoadHandlerCompiler::NonexistentFrontend(Handle last, Handle name) { Label miss; @@ -821,11 +818,11 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle type, Handle last_map; if (last.is_null()) { holder = receiver(); - last_map = IC::TypeToMap(*type, isolate()); + last_map = IC::TypeToMap(*type(), isolate()); // If |type| has null as its prototype, |last| is Handle::null(). ASSERT(last_map->prototype() == isolate()->heap()->null_value()); } else { - holder = FrontendHeader(type, receiver(), last, name, &miss); + holder = FrontendHeader(receiver(), last, name, &miss); last_map = handle(last->map()); } @@ -846,9 +843,10 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle type, // If the last object in the prototype chain is a global object, // check that the global property cell is empty. if (last_map->IsJSGlobalObjectMap()) { - Handle global = last.is_null() - ? Handle::cast(type->AsConstant()->Value()) - : Handle::cast(last); + Handle global = + last.is_null() + ? Handle::cast(type()->AsConstant()->Value()) + : Handle::cast(last); GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); } @@ -857,39 +855,38 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle type, Handle NamedLoadHandlerCompiler::CompileLoadField( - Handle type, Handle holder, Handle name, - FieldIndex field, Representation representation) { - Register reg = Frontend(type, receiver(), holder, name); + Handle holder, Handle name, FieldIndex field, + Representation representation) { + Register reg = Frontend(receiver(), holder, name); GenerateLoadField(reg, holder, field, representation); return GetCode(kind(), Code::FAST, name); } Handle NamedLoadHandlerCompiler::CompileLoadConstant( - Handle type, Handle holder, Handle name, - Handle value) { - Frontend(type, receiver(), holder, name); + Handle holder, Handle name, Handle value) { + Frontend(receiver(), holder, name); GenerateLoadConstant(value); return GetCode(kind(), Code::FAST, name); } Handle NamedLoadHandlerCompiler::CompileLoadCallback( - Handle type, Handle holder, Handle name, + Handle holder, Handle name, Handle callback) { - Register reg = CallbackFrontend(type, receiver(), holder, name, callback); + Register reg = CallbackFrontend(receiver(), holder, name, callback); GenerateLoadCallback(reg, callback); return GetCode(kind(), Code::FAST, name); } Handle NamedLoadHandlerCompiler::CompileLoadCallback( - Handle type, Handle holder, Handle name, + Handle holder, Handle name, const CallOptimization& call_optimization) { ASSERT(call_optimization.is_simple_api_call()); Handle callback = call_optimization.constant_function(); - CallbackFrontend(type, receiver(), holder, name, callback); - Handlereceiver_map = IC::TypeToMap(*type, isolate()); + CallbackFrontend(receiver(), holder, name, callback); + Handle receiver_map = IC::TypeToMap(*type(), isolate()); GenerateFastApiCall( masm(), call_optimization, receiver_map, receiver(), scratch1(), false, 0, NULL); @@ -898,7 +895,7 @@ Handle NamedLoadHandlerCompiler::CompileLoadCallback( Handle NamedLoadHandlerCompiler::CompileLoadInterceptor( - Handle type, Handle holder, Handle name) { + Handle holder, Handle name) { // Perform a lookup after the interceptor. LookupResult lookup(isolate()); holder->LookupOwnRealNamedProperty(name, &lookup); @@ -909,10 +906,10 @@ Handle NamedLoadHandlerCompiler::CompileLoadInterceptor( } } - Register reg = Frontend(type, receiver(), holder, name); + Register reg = Frontend(receiver(), holder, name); // TODO(368): Compile in the whole chain: all the interceptors in // prototypes and ultimate answer. - GenerateLoadInterceptor(reg, type, holder, &lookup, name); + GenerateLoadInterceptor(reg, holder, &lookup, name); return GetCode(kind(), Code::FAST, name); } @@ -929,8 +926,8 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( } else { // We found FIELD property in prototype chain of interceptor's holder. // Retrieve a field from field's holder. - Register reg = Frontend(IC::CurrentTypeOf(interceptor_holder, isolate()), - interceptor_reg, holder, name); + set_type_for_object(interceptor_holder); + Register reg = Frontend(interceptor_reg, holder, name); GenerateLoadField( reg, holder, field, lookup->representation()); } @@ -942,9 +939,8 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); ASSERT(callback->getter() != NULL); - Register reg = - CallbackFrontend(IC::CurrentTypeOf(interceptor_holder, isolate()), - interceptor_reg, holder, name, callback); + set_type_for_object(interceptor_holder); + Register reg = CallbackFrontend(interceptor_reg, holder, name, callback); GenerateLoadCallback(reg, callback); } } @@ -964,10 +960,9 @@ Handle PropertyICCompiler::CompileMonomorphic(Handle type, Handle NamedLoadHandlerCompiler::CompileLoadViaGetter( - Handle type, Handle holder, Handle name, - Handle getter) { - Frontend(type, receiver(), holder, name); - GenerateLoadViaGetter(masm(), type, receiver(), getter); + Handle holder, Handle name, Handle getter) { + Frontend(receiver(), holder, name); + GenerateLoadViaGetter(masm(), type(), receiver(), getter); return GetCode(kind(), Code::FAST, name); } @@ -995,8 +990,7 @@ Handle NamedStoreHandlerCompiler::CompileStoreTransition( } while (!iter.IsAtEnd()); } - Register holder_reg = FrontendHeader(IC::CurrentTypeOf(object, isolate()), - receiver(), holder, name, &miss); + Register holder_reg = FrontendHeader(receiver(), holder, name, &miss); // If no property was found, and the holder (the last object in the // prototype chain) is in slow mode, we need to do a negative lookup on the @@ -1030,8 +1024,7 @@ Handle NamedStoreHandlerCompiler::CompileStoreField( Handle object, LookupResult* lookup, Handle name) { Label miss; - FrontendHeader(IC::CurrentTypeOf(object, isolate()), receiver(), object, name, - &miss); + FrontendHeader(receiver(), object, name, &miss); // Generate store field code. GenerateStoreField(masm(), @@ -1071,9 +1064,8 @@ Handle NamedStoreHandlerCompiler::CompileStoreArrayLength( Handle NamedStoreHandlerCompiler::CompileStoreViaSetter( Handle object, Handle holder, Handle name, Handle setter) { - Handle type = IC::CurrentTypeOf(object, isolate()); - Frontend(type, receiver(), holder, name); - GenerateStoreViaSetter(masm(), type, receiver(), setter); + Frontend(receiver(), holder, name); + GenerateStoreViaSetter(masm(), type(), receiver(), setter); return GetCode(kind(), Code::FAST, name); } @@ -1082,7 +1074,7 @@ Handle NamedStoreHandlerCompiler::CompileStoreViaSetter( Handle NamedStoreHandlerCompiler::CompileStoreCallback( Handle object, Handle holder, Handle name, const CallOptimization& call_optimization) { - Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); + Frontend(receiver(), holder, name); Register values[] = { value() }; GenerateFastApiCall( masm(), call_optimization, handle(object->map()), diff --git a/src/stub-cache.h b/src/stub-cache.h index 263331a..f3a330b 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -374,22 +374,21 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler { protected: PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, - CacheHolderFlag cache_holder) - : PropertyAccessCompiler(isolate, kind, cache_holder) {} + Handle type, CacheHolderFlag cache_holder) + : PropertyAccessCompiler(isolate, kind, cache_holder), type_(type) {} virtual ~PropertyHandlerCompiler() {} - virtual Register FrontendHeader(Handle type, Register object_reg, - Handle holder, Handle name, - Label* miss) { + virtual Register FrontendHeader(Register object_reg, Handle holder, + Handle name, Label* miss) { UNREACHABLE(); return receiver(); } virtual void FrontendFooter(Handle name, Label* miss) { UNREACHABLE(); } - Register Frontend(Handle type, Register object_reg, - Handle holder, Handle name); + Register Frontend(Register object_reg, Handle holder, + Handle name); // TODO(verwaest): Make non-static. static void GenerateFastApiCall(MacroAssembler* masm, @@ -431,67 +430,56 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler { // register is only clobbered if it the same as the holder register. The // function returns a register containing the holder - either object_reg or // holder_reg. - Register CheckPrototypes(Handle type, - Register object_reg, - Handle holder, - Register holder_reg, - Register scratch1, - Register scratch2, - Handle name, - Label* miss, + Register CheckPrototypes(Register object_reg, Handle holder, + Register holder_reg, Register scratch1, + Register scratch2, Handle name, Label* miss, PrototypeCheckType check = CHECK_ALL_MAPS); Handle GetCode(Code::Kind kind, Code::StubType type, Handle name); + void set_type_for_object(Handle object) { + type_ = IC::CurrentTypeOf(object, isolate()); + } + Handle type() const { return type_; } + + private: + Handle type_; }; class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { public: - NamedLoadHandlerCompiler(Isolate* isolate, - CacheHolderFlag cache_holder = kCacheOnReceiver) - : PropertyHandlerCompiler(isolate, Code::LOAD_IC, cache_holder) {} + NamedLoadHandlerCompiler(Isolate* isolate, Handle type, + CacheHolderFlag cache_holder) + : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, cache_holder) {} virtual ~NamedLoadHandlerCompiler() {} - Handle CompileLoadField(Handle type, - Handle holder, - Handle name, + Handle CompileLoadField(Handle holder, Handle name, FieldIndex index, Representation representation); - Handle CompileLoadCallback(Handle type, - Handle holder, - Handle name, + Handle CompileLoadCallback(Handle holder, Handle name, Handle callback); - Handle CompileLoadCallback(Handle type, - Handle holder, - Handle name, + Handle CompileLoadCallback(Handle holder, Handle name, const CallOptimization& call_optimization); - Handle CompileLoadConstant(Handle type, - Handle holder, - Handle name, + Handle CompileLoadConstant(Handle holder, Handle name, Handle value); - Handle CompileLoadInterceptor(Handle type, - Handle holder, + Handle CompileLoadInterceptor(Handle holder, Handle name); - Handle CompileLoadViaGetter(Handle type, - Handle holder, - Handle name, + Handle CompileLoadViaGetter(Handle holder, Handle name, Handle getter); + Handle CompileLoadGlobal(Handle holder, + Handle cell, Handle name, + bool is_dont_delete); + static Handle ComputeLoadNonexistent(Handle name, Handle type); - Handle CompileLoadGlobal(Handle type, - Handle holder, - Handle cell, - Handle name, - bool is_dont_delete); - static void GenerateLoadViaGetter(MacroAssembler* masm, Handle type, Register receiver, Handle getter); @@ -518,20 +506,16 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { static const int kInterceptorArgsLength = 4; protected: - virtual Register FrontendHeader(Handle type, Register object_reg, - Handle holder, Handle name, - Label* miss); + virtual Register FrontendHeader(Register object_reg, Handle holder, + Handle name, Label* miss); virtual void FrontendFooter(Handle name, Label* miss); private: - Register CallbackFrontend(Handle type, Register object_reg, - Handle holder, Handle name, - Handle callback); - Handle CompileLoadNonexistent(Handle type, - Handle last, Handle name); - void NonexistentFrontend(Handle type, Handle last, - Handle name); + Register CallbackFrontend(Register object_reg, Handle holder, + Handle name, Handle callback); + Handle CompileLoadNonexistent(Handle last, Handle name); + void NonexistentFrontend(Handle last, Handle name); void GenerateLoadField(Register reg, Handle holder, @@ -543,7 +527,6 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { void GenerateLoadCallback(const CallOptimization& call_optimization, Handle receiver_map); void GenerateLoadInterceptor(Register holder_reg, - Handle object, Handle holder, LookupResult* lookup, Handle name); @@ -570,8 +553,9 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { public: - explicit NamedStoreHandlerCompiler(Isolate* isolate) - : PropertyHandlerCompiler(isolate, Code::STORE_IC, kCacheOnReceiver) {} + explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle type) + : PropertyHandlerCompiler(isolate, Code::STORE_IC, type, + kCacheOnReceiver) {} virtual ~NamedStoreHandlerCompiler() {} @@ -614,9 +598,8 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { } protected: - virtual Register FrontendHeader(Handle type, Register object_reg, - Handle holder, Handle name, - Label* miss); + virtual Register FrontendHeader(Register object_reg, Handle holder, + Handle name, Label* miss); virtual void FrontendFooter(Handle name, Label* miss); void GenerateRestoreName(MacroAssembler* masm, Label* label, @@ -672,7 +655,7 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler { public: explicit ElementHandlerCompiler(Isolate* isolate) : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC, - kCacheOnReceiver) {} + Handle::null(), kCacheOnReceiver) {} virtual ~ElementHandlerCompiler() {} diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index c263894..358605c 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -633,10 +633,10 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, Register PropertyHandlerCompiler::CheckPrototypes( - Handle type, Register object_reg, Handle holder, - Register holder_reg, Register scratch1, Register scratch2, - Handle name, Label* miss, PrototypeCheckType check) { - Handle receiver_map(IC::TypeToMap(*type, isolate())); + Register object_reg, Handle holder, Register holder_reg, + Register scratch1, Register scratch2, Handle name, Label* miss, + PrototypeCheckType check) { + Handle receiver_map(IC::TypeToMap(*type(), isolate())); // Make sure there's no overlap between holder and object registers. ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); @@ -650,8 +650,8 @@ Register PropertyHandlerCompiler::CheckPrototypes( int depth = 0; Handle current = Handle::null(); - if (type->IsConstant()) { - current = Handle::cast(type->AsConstant()->Value()); + if (type()->IsConstant()) { + current = Handle::cast(type()->AsConstant()->Value()); } Handle prototype = Handle::null(); Handle current_map = receiver_map; @@ -765,14 +765,13 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle name, Label* miss) { } -Register NamedLoadHandlerCompiler::CallbackFrontend(Handle type, - Register object_reg, +Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Handle holder, Handle name, Handle callback) { Label miss; - Register reg = FrontendHeader(type, object_reg, holder, name, &miss); + Register reg = FrontendHeader(object_reg, holder, name, &miss); if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { ASSERT(!reg.is(scratch2())); @@ -875,9 +874,8 @@ void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle value) { void NamedLoadHandlerCompiler::GenerateLoadInterceptor( - Register holder_reg, Handle object, - Handle interceptor_holder, LookupResult* lookup, - Handle name) { + Register holder_reg, Handle interceptor_holder, + LookupResult* lookup, Handle name) { ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); @@ -890,10 +888,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( compile_followup_inline = true; } else if (lookup->type() == CALLBACKS && lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { - ExecutableAccessorInfo* callback = - ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); - compile_followup_inline = callback->getter() != NULL && - callback->IsCompatibleReceiver(*object); + Handle callback( + ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); + compile_followup_inline = + callback->getter() != NULL && + ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, + type()); } } @@ -967,8 +967,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( Handle NamedStoreHandlerCompiler::CompileStoreCallback( Handle object, Handle holder, Handle name, Handle callback) { - Register holder_reg = - Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); + Register holder_reg = Frontend(receiver(), holder, name); __ PopReturnAddressTo(scratch1()); __ Push(receiver()); @@ -1103,8 +1102,8 @@ Handle PropertyICCompiler::CompileKeyedStorePolymorphic( Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle type, Handle last, Handle name) { - NonexistentFrontend(type, last, name); + Handle last, Handle name) { + NonexistentFrontend(last, name); // Return undefined if maps of the full prototype chain are still the // same and no global property with this name contains a value. @@ -1192,30 +1191,27 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( Handle NamedLoadHandlerCompiler::CompileLoadGlobal( - Handle type, Handle global, - Handle cell, Handle name, bool is_dont_delete) { + Handle global, Handle cell, Handle name, + bool is_dont_delete) { Label miss; - // TODO(verwaest): Directly store to rax. Currently we cannot do this, since - // rax is used as receiver(), which we would otherwise clobber before a - // potential miss. - FrontendHeader(type, receiver(), global, name, &miss); + FrontendHeader(receiver(), global, name, &miss); // Get the value from the cell. - __ Move(rbx, cell); - __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); + Register result = StoreIC::ValueRegister(); + __ Move(result, cell); + __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); // Check for deleted property if property can actually be deleted. if (!is_dont_delete) { - __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); + __ CompareRoot(result, Heap::kTheHoleValueRootIndex); __ j(equal, &miss); } else if (FLAG_debug_code) { - __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); + __ CompareRoot(result, Heap::kTheHoleValueRootIndex); __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); } Counters* counters = isolate()->counters(); __ IncrementCounter(counters->named_load_global_stub(), 1); - __ movp(rax, rbx); __ ret(0); FrontendFooter(name, &miss); -- 2.7.4