Commit 7378f07a authored by verwaest@chromium.org's avatar verwaest@chromium.org

Encapsulate the holder in the PropertyHolderCompilers

BUG=
R=ishell@chromium.org

Review URL: https://codereview.chromium.org/422023003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22704 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a56c9170
...@@ -311,10 +311,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( ...@@ -311,10 +311,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
// may be clobbered. Upon branch to miss_label, the receiver and name // may be clobbered. Upon branch to miss_label, the receiver and name
// registers have their original values. // registers have their original values.
void NamedStoreHandlerCompiler::GenerateStoreTransition( void NamedStoreHandlerCompiler::GenerateStoreTransition(
MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
Handle<Map> transition, Handle<Name> name, Register receiver_reg, Handle<Name> name, Register receiver_reg, Register storage_reg,
Register storage_reg, Register value_reg, Register scratch1, Register value_reg, Register scratch1, Register scratch2, Register scratch3,
Register scratch2, Register scratch3, Label* miss_label, Label* slow) { Label* miss_label, Label* slow) {
// r0 : value // r0 : value
Label exit; Label exit;
...@@ -370,13 +370,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -370,13 +370,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
__ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
} }
// Stub never generated for non-global objects that require access // Stub never generated for objects that require access checks.
// checks. ASSERT(!transition->is_access_check_needed());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
// Perform map transition for the receiver if necessary. // Perform map transition for the receiver if necessary.
if (details.type() == FIELD && if (details.type() == FIELD &&
object->map()->unused_property_fields() == 0) { Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value. // The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array. // We jump to a runtime call that extends the properties array.
__ push(receiver_reg); __ push(receiver_reg);
...@@ -416,14 +415,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -416,14 +415,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
// Adjust for the number of properties stored in the object. Even in the // Adjust for the number of properties stored in the object. Even in the
// face of a transition we can use the old map here because the size of the // face of a transition we can use the old map here because the size of the
// object and the number of in-object properties is not going to change. // object and the number of in-object properties is not going to change.
index -= object->map()->inobject_properties(); index -= transition->inobject_properties();
// TODO(verwaest): Share this code as a code stub. // TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged() SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK; ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
if (index < 0) { if (index < 0) {
// Set the property straight into the object. // Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize); int offset = transition->instance_size() + (index * kPointerSize);
if (representation.IsDouble()) { if (representation.IsDouble()) {
__ str(storage_reg, FieldMemOperand(receiver_reg, offset)); __ str(storage_reg, FieldMemOperand(receiver_reg, offset));
} else { } else {
...@@ -733,8 +732,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, ...@@ -733,8 +732,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
Register PropertyHandlerCompiler::CheckPrototypes( Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Handle<JSObject> holder, Register holder_reg, Register object_reg, Register holder_reg, Register scratch1,
Register scratch1, Register scratch2, Handle<Name> name, Label* miss, Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) { PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
...@@ -753,7 +752,7 @@ Register PropertyHandlerCompiler::CheckPrototypes( ...@@ -753,7 +752,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
} }
Handle<JSObject> prototype = Handle<JSObject>::null(); Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map; Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map()); Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for // Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects. // fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) { while (!current_map.is_identical_to(holder_map)) {
...@@ -865,14 +864,14 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { ...@@ -865,14 +864,14 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<Object> callback) { Handle<Object> callback) {
Label miss; Label miss;
Register reg = FrontendHeader(object_reg, holder, name, &miss); Register reg = FrontendHeader(object_reg, name, &miss);
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { if (!holder()->HasFastProperties()) {
ASSERT(!holder()->IsGlobalObject());
ASSERT(!reg.is(scratch2())); ASSERT(!reg.is(scratch2()));
ASSERT(!reg.is(scratch3())); ASSERT(!reg.is(scratch3()));
ASSERT(!reg.is(scratch4())); ASSERT(!reg.is(scratch4()));
...@@ -909,8 +908,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, ...@@ -909,8 +908,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
void NamedLoadHandlerCompiler::GenerateLoadField( void NamedLoadHandlerCompiler::GenerateLoadField(
Register reg, Handle<JSObject> holder, FieldIndex field, Register reg, FieldIndex field, Representation representation) {
Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg); if (!reg.is(receiver())) __ mov(receiver(), reg);
LoadFieldStub stub(isolate(), field); LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode()); GenerateTailCall(masm(), stub.GetCode());
...@@ -970,11 +968,11 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( ...@@ -970,11 +968,11 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback(
} }
void NamedLoadHandlerCompiler::GenerateLoadInterceptor( void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
Register holder_reg, Handle<JSObject> interceptor_holder, LookupResult* lookup,
LookupResult* lookup, Handle<Name> name) { Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(holder()->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD // So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added // and CALLBACKS, so inline only them, other cases may be added
...@@ -1004,7 +1002,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1004,7 +1002,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// the holder and it is needed should the interceptor return without any // the holder and it is needed should the interceptor return without any
// result. The CALLBACKS case needs the receiver to be passed into C++ code, // result. The CALLBACKS case needs the receiver to be passed into C++ code,
// the FIELD case might cause a miss during the prototype check. // the FIELD case might cause a miss during the prototype check.
bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); bool must_perfrom_prototype_check = *holder() != lookup->holder();
bool must_preserve_receiver_reg = !receiver().is(holder_reg) && bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check); (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
...@@ -1021,7 +1019,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1021,7 +1019,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// interceptor's holder has been compiled before (see a caller // interceptor's holder has been compiled before (see a caller
// of this method.) // of this method.)
CompileCallLoadPropertyWithInterceptor( CompileCallLoadPropertyWithInterceptor(
masm(), receiver(), holder_reg, this->name(), interceptor_holder, masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly); IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's // Check if interceptor provided a value for property. If it's
...@@ -1042,12 +1040,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1042,12 +1040,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// Leave the internal frame. // Leave the internal frame.
} }
GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline } else { // !compile_followup_inline
// Call the runtime system to load the interceptor. // Call the runtime system to load the interceptor.
// Check that the maps haven't changed. // Check that the maps haven't changed.
PushInterceptorArguments(masm(), receiver(), holder_reg, PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
this->name(), interceptor_holder); holder());
ExternalReference ref = ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor),
...@@ -1059,12 +1057,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1059,12 +1057,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Register holder_reg = Frontend(receiver(), holder, name); Register holder_reg = Frontend(receiver(), name);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ push(receiver()); // receiver __ push(receiver()); // receiver
__ push(holder_reg); __ push(holder_reg);
...@@ -1132,7 +1127,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( ...@@ -1132,7 +1127,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
Handle<JSObject> object, Handle<Name> name) { Handle<Name> name) {
__ Push(receiver(), this->name(), value()); __ Push(receiver(), this->name(), value());
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
...@@ -1146,8 +1141,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( ...@@ -1146,8 +1141,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
Handle<JSObject> last, Handle<Name> name) { Handle<Name> name) {
NonexistentFrontend(last, name); NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the // Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value. // same and no global property with this name contains a value.
...@@ -1235,10 +1230,9 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( ...@@ -1235,10 +1230,9 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
bool is_dont_delete) {
Label miss; Label miss;
FrontendHeader(receiver(), global, name, &miss); FrontendHeader(receiver(), name, &miss);
// Get the value from the cell. // Get the value from the cell.
Register result = StoreIC::ValueRegister(); Register result = StoreIC::ValueRegister();
......
...@@ -265,10 +265,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( ...@@ -265,10 +265,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
// may be clobbered. Upon branch to miss_label, the receiver and name registers // may be clobbered. Upon branch to miss_label, the receiver and name registers
// have their original values. // have their original values.
void NamedStoreHandlerCompiler::GenerateStoreTransition( void NamedStoreHandlerCompiler::GenerateStoreTransition(
MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
Handle<Map> transition, Handle<Name> name, Register receiver_reg, Handle<Name> name, Register receiver_reg, Register storage_reg,
Register storage_reg, Register value_reg, Register scratch1, Register value_reg, Register scratch1, Register scratch2, Register scratch3,
Register scratch2, Register scratch3, Label* miss_label, Label* slow) { Label* miss_label, Label* slow) {
Label exit; Label exit;
ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg,
...@@ -325,12 +325,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -325,12 +325,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
NoReg, MUTABLE); NoReg, MUTABLE);
} }
// Stub never generated for non-global objects that require access checks. // Stub never generated for objects that require access checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); ASSERT(!transition->is_access_check_needed());
// Perform map transition for the receiver if necessary. // Perform map transition for the receiver if necessary.
if ((details.type() == FIELD) && if (details.type() == FIELD &&
(object->map()->unused_property_fields() == 0)) { Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value. // The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array. // We jump to a runtime call that extends the properties array.
__ Mov(scratch1, Operand(transition)); __ Mov(scratch1, Operand(transition));
...@@ -369,7 +369,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -369,7 +369,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
// Adjust for the number of properties stored in the object. Even in the // Adjust for the number of properties stored in the object. Even in the
// face of a transition we can use the old map here because the size of the // face of a transition we can use the old map here because the size of the
// object and the number of in-object properties is not going to change. // object and the number of in-object properties is not going to change.
index -= object->map()->inobject_properties(); index -= transition->inobject_properties();
// TODO(verwaest): Share this code as a code stub. // TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged() SmiCheck smi_check = representation.IsTagged()
...@@ -377,7 +377,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -377,7 +377,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
Register prop_reg = representation.IsDouble() ? storage_reg : value_reg; Register prop_reg = representation.IsDouble() ? storage_reg : value_reg;
if (index < 0) { if (index < 0) {
// Set the property straight into the object. // Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize); int offset = transition->instance_size() + (index * kPointerSize);
__ Str(prop_reg, FieldMemOperand(receiver_reg, offset)); __ Str(prop_reg, FieldMemOperand(receiver_reg, offset));
if (!representation.IsSmi()) { if (!representation.IsSmi()) {
...@@ -682,8 +682,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, ...@@ -682,8 +682,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
Register PropertyHandlerCompiler::CheckPrototypes( Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Handle<JSObject> holder, Register holder_reg, Register object_reg, Register holder_reg, Register scratch1,
Register scratch1, Register scratch2, Handle<Name> name, Label* miss, Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) { PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
...@@ -701,7 +701,7 @@ Register PropertyHandlerCompiler::CheckPrototypes( ...@@ -701,7 +701,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
} }
Handle<JSObject> prototype = Handle<JSObject>::null(); Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map; Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map()); Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for // Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects. // fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) { while (!current_map.is_identical_to(holder_map)) {
...@@ -818,12 +818,11 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { ...@@ -818,12 +818,11 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<Object> callback) { Handle<Object> callback) {
Label miss; Label miss;
Register reg = FrontendHeader(object_reg, holder, name, &miss); Register reg = FrontendHeader(object_reg, name, &miss);
// FrontendHeader can return its result into scratch1() so do not // FrontendHeader can return its result into scratch1() so do not
// use it. // use it.
Register scratch2 = this->scratch2(); Register scratch2 = this->scratch2();
...@@ -831,7 +830,8 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, ...@@ -831,7 +830,8 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Register dictionary = this->scratch4(); Register dictionary = this->scratch4();
ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary));
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { if (!holder()->HasFastProperties()) {
ASSERT(holder()->IsGlobalObject());
// Load the properties dictionary. // Load the properties dictionary.
__ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset));
...@@ -863,8 +863,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, ...@@ -863,8 +863,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
void NamedLoadHandlerCompiler::GenerateLoadField( void NamedLoadHandlerCompiler::GenerateLoadField(
Register reg, Handle<JSObject> holder, FieldIndex field, Register reg, FieldIndex field, Representation representation) {
Representation representation) {
__ Mov(receiver(), reg); __ Mov(receiver(), reg);
LoadFieldStub stub(isolate(), field); LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode()); GenerateTailCall(masm(), stub.GetCode());
...@@ -932,13 +931,13 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( ...@@ -932,13 +931,13 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback(
} }
void NamedLoadHandlerCompiler::GenerateLoadInterceptor( void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
Register holder_reg, Handle<JSObject> interceptor_holder, LookupResult* lookup,
LookupResult* lookup, Handle<Name> name) { Handle<Name> name) {
ASSERT(!AreAliased(receiver(), this->name(), ASSERT(!AreAliased(receiver(), this->name(),
scratch1(), scratch2(), scratch3())); scratch1(), scratch2(), scratch3()));
ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(holder()->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD // So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added later. // and CALLBACKS, so inline only them, other cases may be added later.
...@@ -967,7 +966,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -967,7 +966,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// the holder and it is needed should the interceptor return without any // the holder and it is needed should the interceptor return without any
// result. The CALLBACKS case needs the receiver to be passed into C++ code, // result. The CALLBACKS case needs the receiver to be passed into C++ code,
// the FIELD case might cause a miss during the prototype check. // the FIELD case might cause a miss during the prototype check.
bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); bool must_perfrom_prototype_check = *holder() != lookup->holder();
bool must_preserve_receiver_reg = !receiver().Is(holder_reg) && bool must_preserve_receiver_reg = !receiver().Is(holder_reg) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check); (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
...@@ -984,7 +983,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -984,7 +983,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// interceptor's holder has been compiled before (see a caller // interceptor's holder has been compiled before (see a caller
// of this method.) // of this method.)
CompileCallLoadPropertyWithInterceptor( CompileCallLoadPropertyWithInterceptor(
masm(), receiver(), holder_reg, this->name(), interceptor_holder, masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly); IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's // Check if interceptor provided a value for property. If it's
...@@ -1004,12 +1003,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1004,12 +1003,12 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
} }
// Leave the internal frame. // Leave the internal frame.
} }
GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline } else { // !compile_followup_inline
// Call the runtime system to load the interceptor. // Call the runtime system to load the interceptor.
// Check that the maps haven't changed. // Check that the maps haven't changed.
PushInterceptorArguments( PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
masm(), receiver(), holder_reg, this->name(), interceptor_holder); holder());
ExternalReference ref = ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor),
...@@ -1021,10 +1020,10 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1021,10 +1020,10 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback");
Register holder_reg = Frontend(receiver(), holder, name); Register holder_reg = Frontend(receiver(), name);
// Stub never generated for non-global objects that require access checks. // Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
...@@ -1097,7 +1096,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( ...@@ -1097,7 +1096,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
Handle<JSObject> object, Handle<Name> name) { Handle<Name> name) {
Label miss; Label miss;
ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor"); ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor");
...@@ -1115,8 +1114,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( ...@@ -1115,8 +1114,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
Handle<JSObject> last, Handle<Name> name) { Handle<Name> name) {
NonexistentFrontend(last, name); NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the // Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value. // same and no global property with this name contains a value.
...@@ -1205,10 +1204,9 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( ...@@ -1205,10 +1204,9 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
bool is_dont_delete) {
Label miss; Label miss;
FrontendHeader(receiver(), global, name, &miss); FrontendHeader(receiver(), name, &miss);
// Get the value from the cell. // Get the value from the cell.
Register result = StoreIC::ValueRegister(); Register result = StoreIC::ValueRegister();
......
...@@ -417,10 +417,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( ...@@ -417,10 +417,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful. // store is successful.
void NamedStoreHandlerCompiler::GenerateStoreTransition( void NamedStoreHandlerCompiler::GenerateStoreTransition(
MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
Handle<Map> transition, Handle<Name> name, Register receiver_reg, Handle<Name> name, Register receiver_reg, Register storage_reg,
Register storage_reg, Register value_reg, Register scratch1, Register value_reg, Register scratch1, Register scratch2, Register unused,
Register scratch2, Register unused, Label* miss_label, Label* slow) { Label* miss_label, Label* slow) {
int descriptor = transition->LastAdded(); int descriptor = transition->LastAdded();
DescriptorArray* descriptors = transition->instance_descriptors(); DescriptorArray* descriptors = transition->instance_descriptors();
PropertyDetails details = descriptors->GetDetails(descriptor); PropertyDetails details = descriptors->GetDetails(descriptor);
...@@ -469,13 +469,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -469,13 +469,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
__ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
} }
// Stub never generated for non-global objects that require access // Stub never generated for objects that require access checks.
// checks. ASSERT(!transition->is_access_check_needed());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
// Perform map transition for the receiver if necessary. // Perform map transition for the receiver if necessary.
if (details.type() == FIELD && if (details.type() == FIELD &&
object->map()->unused_property_fields() == 0) { Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value. // The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array. // We jump to a runtime call that extends the properties array.
__ pop(scratch1); // Return address. __ pop(scratch1); // Return address.
...@@ -516,14 +515,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -516,14 +515,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
// Adjust for the number of properties stored in the object. Even in the // Adjust for the number of properties stored in the object. Even in the
// face of a transition we can use the old map here because the size of the // face of a transition we can use the old map here because the size of the
// object and the number of in-object properties is not going to change. // object and the number of in-object properties is not going to change.
index -= object->map()->inobject_properties(); index -= transition->inobject_properties();
SmiCheck smi_check = representation.IsTagged() SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK; ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
// TODO(verwaest): Share this code as a code stub. // TODO(verwaest): Share this code as a code stub.
if (index < 0) { if (index < 0) {
// Set the property straight into the object. // Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize); int offset = transition->instance_size() + (index * kPointerSize);
if (representation.IsDouble()) { if (representation.IsDouble()) {
__ mov(FieldOperand(receiver_reg, offset), storage_reg); __ mov(FieldOperand(receiver_reg, offset), storage_reg);
} else { } else {
...@@ -693,8 +692,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, ...@@ -693,8 +692,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
Register PropertyHandlerCompiler::CheckPrototypes( Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Handle<JSObject> holder, Register holder_reg, Register object_reg, Register holder_reg, Register scratch1,
Register scratch1, Register scratch2, Handle<Name> name, Label* miss, Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) { PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
...@@ -712,7 +711,7 @@ Register PropertyHandlerCompiler::CheckPrototypes( ...@@ -712,7 +711,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = Handle<JSObject>::cast(type()->AsConstant()->Value()); current = Handle<JSObject>::cast(type()->AsConstant()->Value());
Handle<JSObject> prototype = Handle<JSObject>::null(); Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map; Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map()); Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for // Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects. // fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) { while (!current_map.is_identical_to(holder_map)) {
...@@ -825,14 +824,14 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { ...@@ -825,14 +824,14 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<Object> callback) { Handle<Object> callback) {
Label miss; Label miss;
Register reg = FrontendHeader(object_reg, holder, name, &miss); Register reg = FrontendHeader(object_reg, name, &miss);
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { if (!holder()->HasFastProperties()) {
ASSERT(!holder()->IsGlobalObject());
ASSERT(!reg.is(scratch2())); ASSERT(!reg.is(scratch2()));
ASSERT(!reg.is(scratch3())); ASSERT(!reg.is(scratch3()));
Register dictionary = scratch1(); Register dictionary = scratch1();
...@@ -882,8 +881,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, ...@@ -882,8 +881,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
void NamedLoadHandlerCompiler::GenerateLoadField( void NamedLoadHandlerCompiler::GenerateLoadField(
Register reg, Handle<JSObject> holder, FieldIndex field, Register reg, FieldIndex field, Representation representation) {
Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg); if (!reg.is(receiver())) __ mov(receiver(), reg);
LoadFieldStub stub(isolate(), field); LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode()); GenerateTailCall(masm(), stub.GetCode());
...@@ -942,11 +940,11 @@ void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { ...@@ -942,11 +940,11 @@ void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
} }
void NamedLoadHandlerCompiler::GenerateLoadInterceptor( void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
Register holder_reg, Handle<JSObject> interceptor_holder, LookupResult* lookup,
LookupResult* lookup, Handle<Name> name) { Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(holder()->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD // So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added // and CALLBACKS, so inline only them, other cases may be added
...@@ -976,7 +974,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -976,7 +974,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// the holder and it is needed should the interceptor return without any // the holder and it is needed should the interceptor return without any
// result. The CALLBACKS case needs the receiver to be passed into C++ code, // result. The CALLBACKS case needs the receiver to be passed into C++ code,
// the FIELD case might cause a miss during the prototype check. // the FIELD case might cause a miss during the prototype check.
bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); bool must_perfrom_prototype_check = *holder() != lookup->holder();
bool must_preserve_receiver_reg = !receiver().is(holder_reg) && bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check); (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
...@@ -995,7 +993,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -995,7 +993,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// interceptor's holder has been compiled before (see a caller // interceptor's holder has been compiled before (see a caller
// of this method.) // of this method.)
CompileCallLoadPropertyWithInterceptor( CompileCallLoadPropertyWithInterceptor(
masm(), receiver(), holder_reg, this->name(), interceptor_holder, masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly); IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's // Check if interceptor provided a value for property. If it's
...@@ -1023,13 +1021,13 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1023,13 +1021,13 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// Leave the internal frame. // Leave the internal frame.
} }
GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline } else { // !compile_followup_inline
// Call the runtime system to load the interceptor. // Call the runtime system to load the interceptor.
// Check that the maps haven't changed. // Check that the maps haven't changed.
__ pop(scratch2()); // save old return address __ pop(scratch2()); // save old return address
PushInterceptorArguments(masm(), receiver(), holder_reg, PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
this->name(), interceptor_holder); holder());
__ push(scratch2()); // restore old return address __ push(scratch2()); // restore old return address
ExternalReference ref = ExternalReference ref =
...@@ -1042,9 +1040,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -1042,9 +1040,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Register holder_reg = Frontend(receiver(), holder, name); Register holder_reg = Frontend(receiver(), name);
__ pop(scratch1()); // remove the return address __ pop(scratch1()); // remove the return address
__ push(receiver()); __ push(receiver());
...@@ -1114,7 +1112,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( ...@@ -1114,7 +1112,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
Handle<JSObject> object, Handle<Name> name) { Handle<Name> name) {
__ pop(scratch1()); // remove the return address __ pop(scratch1()); // remove the return address
__ push(receiver()); __ push(receiver());
__ push(this->name()); __ push(this->name());
...@@ -1172,8 +1170,8 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( ...@@ -1172,8 +1170,8 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
Handle<JSObject> last, Handle<Name> name) { Handle<Name> name) {
NonexistentFrontend(last, name); NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the // Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value. // same and no global property with this name contains a value.
...@@ -1256,11 +1254,10 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( ...@@ -1256,11 +1254,10 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
bool is_dont_delete) {
Label miss; Label miss;
FrontendHeader(receiver(), global, name, &miss); FrontendHeader(receiver(), name, &miss);
// Get the value from the cell. // Get the value from the cell.
Register result = StoreIC::ValueRegister(); Register result = StoreIC::ValueRegister();
if (masm()->serializer_enabled()) { if (masm()->serializer_enabled()) {
......
...@@ -942,7 +942,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, ...@@ -942,7 +942,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object,
Handle<HeapType> type = receiver_type(); Handle<HeapType> type = receiver_type();
Handle<JSObject> holder(lookup->holder()); Handle<JSObject> holder(lookup->holder());
bool receiver_is_holder = object.is_identical_to(holder); bool receiver_is_holder = object.is_identical_to(holder);
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), cache_holder); NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
switch (lookup->type()) { switch (lookup->type()) {
case FIELD: { case FIELD: {
...@@ -950,12 +951,11 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, ...@@ -950,12 +951,11 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object,
if (receiver_is_holder) { if (receiver_is_holder) {
return SimpleFieldLoad(field); return SimpleFieldLoad(field);
} }
return compiler.CompileLoadField(holder, name, field, return compiler.CompileLoadField(name, field, lookup->representation());
lookup->representation());
} }
case CONSTANT: { case CONSTANT: {
Handle<Object> constant(lookup->GetConstant(), isolate()); Handle<Object> constant(lookup->GetConstant(), isolate());
return compiler.CompileLoadConstant(holder, name, constant); return compiler.CompileLoadConstant(name, constant);
} }
case NORMAL: case NORMAL:
if (kind() != Code::LOAD_IC) break; if (kind() != Code::LOAD_IC) break;
...@@ -963,8 +963,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, ...@@ -963,8 +963,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object,
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
Handle<PropertyCell> cell( Handle<PropertyCell> cell(
global->GetPropertyCell(lookup), isolate()); global->GetPropertyCell(lookup), isolate());
Handle<Code> code = compiler.CompileLoadGlobal(global, cell, name, Handle<Code> code =
lookup->IsDontDelete()); compiler.CompileLoadGlobal(cell, name, lookup->IsDontDelete());
// TODO(verwaest): Move caching of these NORMAL stubs outside as well. // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
CacheHolderFlag flag; CacheHolderFlag flag;
Handle<Map> stub_holder_map = Handle<Map> stub_holder_map =
...@@ -1001,7 +1001,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, ...@@ -1001,7 +1001,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object,
type)) { type)) {
break; break;
} }
return compiler.CompileLoadCallback(holder, name, info); if (holder->IsGlobalObject()) break;
return compiler.CompileLoadCallback(name, info);
} else if (callback->IsAccessorPair()) { } else if (callback->IsAccessorPair()) {
Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
isolate()); isolate());
...@@ -1019,9 +1020,9 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, ...@@ -1019,9 +1020,9 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object,
CallOptimization call_optimization(function); CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() && if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(object, holder)) { call_optimization.IsCompatibleReceiver(object, holder)) {
return compiler.CompileLoadCallback(holder, name, call_optimization); return compiler.CompileLoadCallback(name, call_optimization);
} }
return compiler.CompileLoadViaGetter(holder, name, function); return compiler.CompileLoadViaGetter(name, function);
} }
// TODO(dcarney): Handle correctly. // TODO(dcarney): Handle correctly.
ASSERT(callback->IsDeclaredAccessorInfo()); ASSERT(callback->IsDeclaredAccessorInfo());
...@@ -1029,7 +1030,7 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, ...@@ -1029,7 +1030,7 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object,
} }
case INTERCEPTOR: case INTERCEPTOR:
ASSERT(HasInterceptorGetter(*holder)); ASSERT(HasInterceptorGetter(*holder));
return compiler.CompileLoadInterceptor(holder, name); return compiler.CompileLoadInterceptor(name);
default: default:
break; break;
} }
...@@ -1394,7 +1395,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, ...@@ -1394,7 +1395,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver = Handle<JSObject>::cast(object); Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<JSObject> holder(lookup->holder()); Handle<JSObject> holder(lookup->holder());
NamedStoreHandlerCompiler compiler(isolate(), receiver_type()); NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
if (lookup->IsTransition()) { if (lookup->IsTransition()) {
// Explicitly pass in the receiver map since LookupForWrite may have // Explicitly pass in the receiver map since LookupForWrite may have
...@@ -1403,13 +1404,12 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, ...@@ -1403,13 +1404,12 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
PropertyDetails details = lookup->GetPropertyDetails(); PropertyDetails details = lookup->GetPropertyDetails();
if (details.type() != CALLBACKS && details.attributes() == NONE) { if (details.type() != CALLBACKS && details.attributes() == NONE) {
return compiler.CompileStoreTransition( return compiler.CompileStoreTransition(lookup, transition, name);
receiver, lookup, transition, name);
} }
} else { } else {
switch (lookup->type()) { switch (lookup->type()) {
case FIELD: case FIELD:
return compiler.CompileStoreField(receiver, lookup, name); return compiler.CompileStoreField(lookup, name);
case NORMAL: case NORMAL:
if (kind() == Code::KEYED_STORE_IC) break; if (kind() == Code::KEYED_STORE_IC) break;
if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
...@@ -1444,7 +1444,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, ...@@ -1444,7 +1444,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
isolate(), info, receiver_type())) { isolate(), info, receiver_type())) {
break; break;
} }
return compiler.CompileStoreCallback(receiver, holder, name, info); return compiler.CompileStoreCallback(receiver, name, info);
} else if (callback->IsAccessorPair()) { } else if (callback->IsAccessorPair()) {
Handle<Object> setter( Handle<Object> setter(
Handle<AccessorPair>::cast(callback)->setter(), isolate()); Handle<AccessorPair>::cast(callback)->setter(), isolate());
...@@ -1455,11 +1455,11 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, ...@@ -1455,11 +1455,11 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
CallOptimization call_optimization(function); CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() && if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(receiver, holder)) { call_optimization.IsCompatibleReceiver(receiver, holder)) {
return compiler.CompileStoreCallback( return compiler.CompileStoreCallback(receiver, name,
receiver, holder, name, call_optimization); call_optimization);
} }
return compiler.CompileStoreViaSetter( return compiler.CompileStoreViaSetter(
receiver, holder, name, Handle<JSFunction>::cast(setter)); receiver, name, Handle<JSFunction>::cast(setter));
} }
// TODO(dcarney): Handle correctly. // TODO(dcarney): Handle correctly.
ASSERT(callback->IsDeclaredAccessorInfo()); ASSERT(callback->IsDeclaredAccessorInfo());
...@@ -1468,7 +1468,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, ...@@ -1468,7 +1468,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
case INTERCEPTOR: case INTERCEPTOR:
if (kind() == Code::KEYED_STORE_IC) break; if (kind() == Code::KEYED_STORE_IC) break;
ASSERT(HasInterceptorSetter(*holder)); ASSERT(HasInterceptorSetter(*holder));
return compiler.CompileStoreInterceptor(receiver, name); return compiler.CompileStoreInterceptor(name);
case CONSTANT: case CONSTANT:
break; break;
case NONEXISTENT: case NONEXISTENT:
......
This diff is collapsed.
This diff is collapsed.
...@@ -374,10 +374,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( ...@@ -374,10 +374,10 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful. // store is successful.
void NamedStoreHandlerCompiler::GenerateStoreTransition( void NamedStoreHandlerCompiler::GenerateStoreTransition(
MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
Handle<Map> transition, Handle<Name> name, Register receiver_reg, Handle<Name> name, Register receiver_reg, Register storage_reg,
Register storage_reg, Register value_reg, Register scratch1, Register value_reg, Register scratch1, Register scratch2, Register unused,
Register scratch2, Register unused, Label* miss_label, Label* slow) { Label* miss_label, Label* slow) {
int descriptor = transition->LastAdded(); int descriptor = transition->LastAdded();
DescriptorArray* descriptors = transition->instance_descriptors(); DescriptorArray* descriptors = transition->instance_descriptors();
PropertyDetails details = descriptors->GetDetails(descriptor); PropertyDetails details = descriptors->GetDetails(descriptor);
...@@ -425,13 +425,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -425,13 +425,12 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
__ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
} }
// Stub never generated for non-global objects that require access // Stub never generated for objects that require access checks.
// checks. ASSERT(!transition->is_access_check_needed());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
// Perform map transition for the receiver if necessary. // Perform map transition for the receiver if necessary.
if (details.type() == FIELD && if (details.type() == FIELD &&
object->map()->unused_property_fields() == 0) { Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value. // The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array. // We jump to a runtime call that extends the properties array.
__ PopReturnAddressTo(scratch1); __ PopReturnAddressTo(scratch1);
...@@ -472,14 +471,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( ...@@ -472,14 +471,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
// Adjust for the number of properties stored in the object. Even in the // Adjust for the number of properties stored in the object. Even in the
// face of a transition we can use the old map here because the size of the // face of a transition we can use the old map here because the size of the
// object and the number of in-object properties is not going to change. // object and the number of in-object properties is not going to change.
index -= object->map()->inobject_properties(); index -= transition->inobject_properties();
// TODO(verwaest): Share this code as a code stub. // TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged() SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK; ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
if (index < 0) { if (index < 0) {
// Set the property straight into the object. // Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize); int offset = transition->instance_size() + (index * kPointerSize);
if (representation.IsDouble()) { if (representation.IsDouble()) {
__ movp(FieldOperand(receiver_reg, offset), storage_reg); __ movp(FieldOperand(receiver_reg, offset), storage_reg);
} else { } else {
...@@ -633,8 +632,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, ...@@ -633,8 +632,8 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
Register PropertyHandlerCompiler::CheckPrototypes( Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Handle<JSObject> holder, Register holder_reg, Register object_reg, Register holder_reg, Register scratch1,
Register scratch1, Register scratch2, Handle<Name> name, Label* miss, Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) { PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
...@@ -655,7 +654,7 @@ Register PropertyHandlerCompiler::CheckPrototypes( ...@@ -655,7 +654,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
} }
Handle<JSObject> prototype = Handle<JSObject>::null(); Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map; Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder->map()); Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for // Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects. // fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) { while (!current_map.is_identical_to(holder_map)) {
...@@ -766,14 +765,14 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { ...@@ -766,14 +765,14 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<Object> callback) { Handle<Object> callback) {
Label miss; Label miss;
Register reg = FrontendHeader(object_reg, holder, name, &miss); Register reg = FrontendHeader(object_reg, name, &miss);
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { if (!holder()->HasFastProperties()) {
ASSERT(!holder()->IsGlobalObject());
ASSERT(!reg.is(scratch2())); ASSERT(!reg.is(scratch2()));
ASSERT(!reg.is(scratch3())); ASSERT(!reg.is(scratch3()));
ASSERT(!reg.is(scratch4())); ASSERT(!reg.is(scratch4()));
...@@ -814,8 +813,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, ...@@ -814,8 +813,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
void NamedLoadHandlerCompiler::GenerateLoadField( void NamedLoadHandlerCompiler::GenerateLoadField(
Register reg, Handle<JSObject> holder, FieldIndex field, Register reg, FieldIndex field, Representation representation) {
Representation representation) {
if (!reg.is(receiver())) __ movp(receiver(), reg); if (!reg.is(receiver())) __ movp(receiver(), reg);
LoadFieldStub stub(isolate(), field); LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode()); GenerateTailCall(masm(), stub.GetCode());
...@@ -873,11 +871,11 @@ void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { ...@@ -873,11 +871,11 @@ void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
} }
void NamedLoadHandlerCompiler::GenerateLoadInterceptor( void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
Register holder_reg, Handle<JSObject> interceptor_holder, LookupResult* lookup,
LookupResult* lookup, Handle<Name> name) { Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(holder()->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD // So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added // and CALLBACKS, so inline only them, other cases may be added
...@@ -907,7 +905,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -907,7 +905,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// the holder and it is needed should the interceptor return without any // the holder and it is needed should the interceptor return without any
// result. The CALLBACKS case needs the receiver to be passed into C++ code, // result. The CALLBACKS case needs the receiver to be passed into C++ code,
// the FIELD case might cause a miss during the prototype check. // the FIELD case might cause a miss during the prototype check.
bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); bool must_perfrom_prototype_check = *holder() != lookup->holder();
bool must_preserve_receiver_reg = !receiver().is(holder_reg) && bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check); (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
...@@ -926,7 +924,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -926,7 +924,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// interceptor's holder has been compiled before (see a caller // interceptor's holder has been compiled before (see a caller
// of this method.) // of this method.)
CompileCallLoadPropertyWithInterceptor( CompileCallLoadPropertyWithInterceptor(
masm(), receiver(), holder_reg, this->name(), interceptor_holder, masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly); IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's // Check if interceptor provided a value for property. If it's
...@@ -947,13 +945,13 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -947,13 +945,13 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
// Leave the internal frame. // Leave the internal frame.
} }
GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline } else { // !compile_followup_inline
// Call the runtime system to load the interceptor. // Call the runtime system to load the interceptor.
// Check that the maps haven't changed. // Check that the maps haven't changed.
__ PopReturnAddressTo(scratch2()); __ PopReturnAddressTo(scratch2());
PushInterceptorArguments(masm(), receiver(), holder_reg, PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
this->name(), interceptor_holder); holder());
__ PushReturnAddressFrom(scratch2()); __ PushReturnAddressFrom(scratch2());
ExternalReference ref = ExternalReference( ExternalReference ref = ExternalReference(
...@@ -965,9 +963,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( ...@@ -965,9 +963,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Register holder_reg = Frontend(receiver(), holder, name); Register holder_reg = Frontend(receiver(), name);
__ PopReturnAddressTo(scratch1()); __ PopReturnAddressTo(scratch1());
__ Push(receiver()); __ Push(receiver());
...@@ -1037,7 +1035,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( ...@@ -1037,7 +1035,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
Handle<JSObject> object, Handle<Name> name) { Handle<Name> name) {
__ PopReturnAddressTo(scratch1()); __ PopReturnAddressTo(scratch1());
__ Push(receiver()); __ Push(receiver());
__ Push(this->name()); __ Push(this->name());
...@@ -1102,8 +1100,8 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( ...@@ -1102,8 +1100,8 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
Handle<JSObject> last, Handle<Name> name) { Handle<Name> name) {
NonexistentFrontend(last, name); NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the // Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value. // same and no global property with this name contains a value.
...@@ -1191,10 +1189,9 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( ...@@ -1191,10 +1189,9 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
bool is_dont_delete) {
Label miss; Label miss;
FrontendHeader(receiver(), global, name, &miss); FrontendHeader(receiver(), name, &miss);
// Get the value from the cell. // Get the value from the cell.
Register result = StoreIC::ValueRegister(); Register result = StoreIC::ValueRegister();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment