// may be clobbered. Upon branch to miss_label, the receiver and name
// registers have their original values.
void NamedStoreHandlerCompiler::GenerateStoreTransition(
- MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup,
- Handle<Map> transition, Handle<Name> name, Register receiver_reg,
- Register storage_reg, Register value_reg, Register scratch1,
- Register scratch2, Register scratch3, Label* miss_label, Label* slow) {
+ MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
+ Handle<Name> name, Register receiver_reg, Register storage_reg,
+ Register value_reg, Register scratch1, Register scratch2, Register scratch3,
+ Label* miss_label, Label* slow) {
// r0 : value
Label exit;
__ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
}
- // Stub never generated for non-global objects that require access
- // checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+ // Stub never generated for objects that require access checks.
+ ASSERT(!transition->is_access_check_needed());
// Perform map transition for the receiver if necessary.
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.
// We jump to a runtime call that extends the properties array.
__ push(receiver_reg);
// 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
// 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.
SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
if (index < 0) {
// 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()) {
__ str(storage_reg, FieldMemOperand(receiver_reg, offset));
} else {
Register PropertyHandlerCompiler::CheckPrototypes(
- Register object_reg, Handle<JSObject> holder, Register holder_reg,
- Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ Register object_reg, Register holder_reg, Register scratch1,
+ Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
}
Handle<JSObject> prototype = Handle<JSObject>::null();
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
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
- Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
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(scratch3()));
ASSERT(!reg.is(scratch4()));
void NamedLoadHandlerCompiler::GenerateLoadField(
- Register reg, Handle<JSObject> holder, FieldIndex field,
- Representation representation) {
+ Register reg, FieldIndex field, Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg);
LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
-void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<JSObject> interceptor_holder,
- LookupResult* lookup, Handle<Name> name) {
- ASSERT(interceptor_holder->HasNamedInterceptor());
- ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
+void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
+ LookupResult* lookup,
+ Handle<Name> name) {
+ ASSERT(holder()->HasNamedInterceptor());
+ ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added
// 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,
// 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) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
// interceptor's holder has been compiled before (see a caller
// of this method.)
CompileCallLoadPropertyWithInterceptor(
- masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's
// Leave the internal frame.
}
- GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
+ GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
- PushInterceptorArguments(masm(), receiver(), holder_reg,
- this->name(), interceptor_holder);
+ PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
+ holder());
ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor),
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
+ Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg = Frontend(receiver(), holder, name);
-
- // Stub never generated for non-global objects that require access checks.
- ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
+ Register holder_reg = Frontend(receiver(), name);
__ push(receiver()); // receiver
__ push(holder_reg);
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
- Handle<JSObject> object, Handle<Name> name) {
+ Handle<Name> name) {
__ Push(receiver(), this->name(), value());
// Do tail-call to the runtime system.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(last, name);
+ Handle<Name> name) {
+ NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
- bool is_dont_delete) {
+ Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Label miss;
- FrontendHeader(receiver(), global, name, &miss);
+ FrontendHeader(receiver(), name, &miss);
// Get the value from the cell.
Register result = StoreIC::ValueRegister();
// may be clobbered. Upon branch to miss_label, the receiver and name registers
// have their original values.
void NamedStoreHandlerCompiler::GenerateStoreTransition(
- MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup,
- Handle<Map> transition, Handle<Name> name, Register receiver_reg,
- Register storage_reg, Register value_reg, Register scratch1,
- Register scratch2, Register scratch3, Label* miss_label, Label* slow) {
+ MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
+ Handle<Name> name, Register receiver_reg, Register storage_reg,
+ Register value_reg, Register scratch1, Register scratch2, Register scratch3,
+ Label* miss_label, Label* slow) {
Label exit;
ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg,
NoReg, MUTABLE);
}
- // Stub never generated for non-global objects that require access checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+ // Stub never generated for objects that require access checks.
+ ASSERT(!transition->is_access_check_needed());
// Perform map transition for the receiver if necessary.
- if ((details.type() == FIELD) &&
- (object->map()->unused_property_fields() == 0)) {
+ if (details.type() == FIELD &&
+ Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ Mov(scratch1, Operand(transition));
// 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
// 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.
SmiCheck smi_check = representation.IsTagged()
Register prop_reg = representation.IsDouble() ? storage_reg : value_reg;
if (index < 0) {
// 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));
if (!representation.IsSmi()) {
Register PropertyHandlerCompiler::CheckPrototypes(
- Register object_reg, Handle<JSObject> holder, Register holder_reg,
- Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ Register object_reg, Register holder_reg, Register scratch1,
+ Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
}
Handle<JSObject> prototype = Handle<JSObject>::null();
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
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
- Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
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
// use it.
Register scratch2 = this->scratch2();
Register dictionary = this->scratch4();
ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary));
- if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
+ if (!holder()->HasFastProperties()) {
+ ASSERT(holder()->IsGlobalObject());
// Load the properties dictionary.
__ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset));
void NamedLoadHandlerCompiler::GenerateLoadField(
- Register reg, Handle<JSObject> holder, FieldIndex field,
- Representation representation) {
+ Register reg, FieldIndex field, Representation representation) {
__ Mov(receiver(), reg);
LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
-void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<JSObject> interceptor_holder,
- LookupResult* lookup, Handle<Name> name) {
+void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
+ LookupResult* lookup,
+ Handle<Name> name) {
ASSERT(!AreAliased(receiver(), this->name(),
scratch1(), scratch2(), scratch3()));
- ASSERT(interceptor_holder->HasNamedInterceptor());
- ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
+ ASSERT(holder()->HasNamedInterceptor());
+ ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added later.
// 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,
// 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) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
// interceptor's holder has been compiled before (see a caller
// of this method.)
CompileCallLoadPropertyWithInterceptor(
- masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's
}
// Leave the internal frame.
}
- GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
+ GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
- PushInterceptorArguments(
- masm(), receiver(), holder_reg, this->name(), interceptor_holder);
+ PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
+ holder());
ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor),
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
+ Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
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.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
- Handle<JSObject> object, Handle<Name> name) {
+ Handle<Name> name) {
Label miss;
ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor");
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(last, name);
+ Handle<Name> name) {
+ NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
- bool is_dont_delete) {
+ Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Label miss;
- FrontendHeader(receiver(), global, name, &miss);
+ FrontendHeader(receiver(), name, &miss);
// Get the value from the cell.
Register result = StoreIC::ValueRegister();
// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful.
void NamedStoreHandlerCompiler::GenerateStoreTransition(
- MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup,
- Handle<Map> transition, Handle<Name> name, Register receiver_reg,
- Register storage_reg, Register value_reg, Register scratch1,
- Register scratch2, Register unused, Label* miss_label, Label* slow) {
+ MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
+ Handle<Name> name, Register receiver_reg, Register storage_reg,
+ Register value_reg, Register scratch1, Register scratch2, Register unused,
+ Label* miss_label, Label* slow) {
int descriptor = transition->LastAdded();
DescriptorArray* descriptors = transition->instance_descriptors();
PropertyDetails details = descriptors->GetDetails(descriptor);
__ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
}
- // Stub never generated for non-global objects that require access
- // checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+ // Stub never generated for objects that require access checks.
+ ASSERT(!transition->is_access_check_needed());
// Perform map transition for the receiver if necessary.
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.
// We jump to a runtime call that extends the properties array.
__ pop(scratch1); // Return address.
// 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
// 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()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
// TODO(verwaest): Share this code as a code stub.
if (index < 0) {
// 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()) {
__ mov(FieldOperand(receiver_reg, offset), storage_reg);
} else {
Register PropertyHandlerCompiler::CheckPrototypes(
- Register object_reg, Handle<JSObject> holder, Register holder_reg,
- Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ Register object_reg, Register holder_reg, Register scratch1,
+ Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
current = Handle<JSObject>::cast(type()->AsConstant()->Value());
Handle<JSObject> prototype = Handle<JSObject>::null();
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
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
- Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
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(scratch3()));
Register dictionary = scratch1();
void NamedLoadHandlerCompiler::GenerateLoadField(
- Register reg, Handle<JSObject> holder, FieldIndex field,
- Representation representation) {
+ Register reg, FieldIndex field, Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg);
LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
-void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<JSObject> interceptor_holder,
- LookupResult* lookup, Handle<Name> name) {
- ASSERT(interceptor_holder->HasNamedInterceptor());
- ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
+void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
+ LookupResult* lookup,
+ Handle<Name> name) {
+ ASSERT(holder()->HasNamedInterceptor());
+ ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added
// 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,
// 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) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
// interceptor's holder has been compiled before (see a caller
// of this method.)
CompileCallLoadPropertyWithInterceptor(
- masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's
// Leave the internal frame.
}
- GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
+ GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
__ pop(scratch2()); // save old return address
- PushInterceptorArguments(masm(), receiver(), holder_reg,
- this->name(), interceptor_holder);
+ PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
+ holder());
__ push(scratch2()); // restore old return address
ExternalReference ref =
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
+ Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg = Frontend(receiver(), holder, name);
+ Register holder_reg = Frontend(receiver(), name);
__ pop(scratch1()); // remove the return address
__ push(receiver());
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
- Handle<JSObject> object, Handle<Name> name) {
+ Handle<Name> name) {
__ pop(scratch1()); // remove the return address
__ push(receiver());
__ push(this->name());
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(last, name);
+ Handle<Name> name) {
+ NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
- bool is_dont_delete) {
+ Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Label miss;
- FrontendHeader(receiver(), global, name, &miss);
+ FrontendHeader(receiver(), name, &miss);
// Get the value from the cell.
Register result = StoreIC::ValueRegister();
if (masm()->serializer_enabled()) {
Handle<HeapType> type = receiver_type();
Handle<JSObject> holder(lookup->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()) {
case FIELD: {
if (receiver_is_holder) {
return SimpleFieldLoad(field);
}
- return compiler.CompileLoadField(holder, name, field,
- lookup->representation());
+ return compiler.CompileLoadField(name, field, lookup->representation());
}
case CONSTANT: {
Handle<Object> constant(lookup->GetConstant(), isolate());
- return compiler.CompileLoadConstant(holder, name, constant);
+ return compiler.CompileLoadConstant(name, constant);
}
case NORMAL:
if (kind() != Code::LOAD_IC) break;
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
Handle<PropertyCell> cell(
global->GetPropertyCell(lookup), isolate());
- Handle<Code> code = compiler.CompileLoadGlobal(global, cell, name,
- lookup->IsDontDelete());
+ Handle<Code> code =
+ compiler.CompileLoadGlobal(cell, name, lookup->IsDontDelete());
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
CacheHolderFlag flag;
Handle<Map> stub_holder_map =
type)) {
break;
}
- return compiler.CompileLoadCallback(holder, name, info);
+ if (holder->IsGlobalObject()) break;
+ return compiler.CompileLoadCallback(name, info);
} else if (callback->IsAccessorPair()) {
Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
isolate());
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
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.
ASSERT(callback->IsDeclaredAccessorInfo());
}
case INTERCEPTOR:
ASSERT(HasInterceptorGetter(*holder));
- return compiler.CompileLoadInterceptor(holder, name);
+ return compiler.CompileLoadInterceptor(name);
default:
break;
}
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<JSObject> holder(lookup->holder());
- NamedStoreHandlerCompiler compiler(isolate(), receiver_type());
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
if (lookup->IsTransition()) {
// Explicitly pass in the receiver map since LookupForWrite may have
PropertyDetails details = lookup->GetPropertyDetails();
if (details.type() != CALLBACKS && details.attributes() == NONE) {
- return compiler.CompileStoreTransition(
- receiver, lookup, transition, name);
+ return compiler.CompileStoreTransition(lookup, transition, name);
}
} else {
switch (lookup->type()) {
case FIELD:
- return compiler.CompileStoreField(receiver, lookup, name);
+ return compiler.CompileStoreField(lookup, name);
case NORMAL:
if (kind() == Code::KEYED_STORE_IC) break;
if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
isolate(), info, receiver_type())) {
break;
}
- return compiler.CompileStoreCallback(receiver, holder, name, info);
+ return compiler.CompileStoreCallback(receiver, name, info);
} else if (callback->IsAccessorPair()) {
Handle<Object> setter(
Handle<AccessorPair>::cast(callback)->setter(), isolate());
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(receiver, holder)) {
- return compiler.CompileStoreCallback(
- receiver, holder, name, call_optimization);
+ return compiler.CompileStoreCallback(receiver, name,
+ call_optimization);
}
return compiler.CompileStoreViaSetter(
- receiver, holder, name, Handle<JSFunction>::cast(setter));
+ receiver, name, Handle<JSFunction>::cast(setter));
}
// TODO(dcarney): Handle correctly.
ASSERT(callback->IsDeclaredAccessorInfo());
case INTERCEPTOR:
if (kind() == Code::KEYED_STORE_IC) break;
ASSERT(HasInterceptorSetter(*holder));
- return compiler.CompileStoreInterceptor(receiver, name);
+ return compiler.CompileStoreInterceptor(name);
case CONSTANT:
break;
case NONEXISTENT:
cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST);
if (!handler.is_null()) return handler;
- NamedLoadHandlerCompiler compiler(isolate, type, flag);
- handler = compiler.CompileLoadNonexistent(last, cache_name);
+ NamedLoadHandlerCompiler compiler(isolate, type, last, flag);
+ handler = compiler.CompileLoadNonexistent(cache_name);
Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
return handler;
}
Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
- Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
PrototypeCheckType check_type = CHECK_ALL_MAPS;
}
// Check that the maps starting from the prototype haven't changed.
- return CheckPrototypes(object_reg, holder, scratch1(), scratch2(), scratch3(),
- name, miss, check_type);
+ return CheckPrototypes(object_reg, 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(Register object_reg,
- Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
- return CheckPrototypes(object_reg, holder, this->name(), scratch1(),
- scratch2(), name, miss, SKIP_RECEIVER);
+ return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
+ miss, SKIP_RECEIVER);
}
Register PropertyHandlerCompiler::Frontend(Register object_reg,
- Handle<JSObject> holder,
Handle<Name> name) {
Label miss;
- Register reg = FrontendHeader(object_reg, holder, name, &miss);
+ Register reg = FrontendHeader(object_reg, name, &miss);
FrontendFooter(name, &miss);
return reg;
}
-void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<JSObject> last,
- Handle<Name> name) {
+void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) {
Label miss;
- Register holder;
+ Register holder_reg;
Handle<Map> last_map;
- if (last.is_null()) {
- holder = receiver();
+ if (holder().is_null()) {
+ holder_reg = receiver();
last_map = IC::TypeToMap(*type(), isolate());
- // If |type| has null as its prototype, |last| is Handle<JSObject>::null().
+ // If |type| has null as its prototype, |holder()| is
+ // Handle<JSObject>::null().
ASSERT(last_map->prototype() == isolate()->heap()->null_value());
} else {
- holder = FrontendHeader(receiver(), last, name, &miss);
- last_map = handle(last->map());
+ holder_reg = FrontendHeader(receiver(), name, &miss);
+ last_map = handle(holder()->map());
}
- if (last_map->is_dictionary_map() &&
- !last_map->IsJSGlobalObjectMap() &&
- !last_map->IsJSGlobalProxyMap()) {
+ if (last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap()) {
if (!name->IsUniqueName()) {
ASSERT(name->IsString());
name = factory()->InternalizeString(Handle<String>::cast(name));
}
- ASSERT(last.is_null() ||
- last->property_dictionary()->FindEntry(name) ==
+ ASSERT(holder().is_null() ||
+ holder()->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
- GenerateDictionaryNegativeLookup(masm(), &miss, holder, name,
+ GenerateDictionaryNegativeLookup(masm(), &miss, holder_reg, name,
scratch2(), scratch3());
}
// check that the global property cell is empty.
if (last_map->IsJSGlobalObjectMap()) {
Handle<JSGlobalObject> global =
- last.is_null()
+ holder().is_null()
? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value())
- : Handle<JSGlobalObject>::cast(last);
+ : Handle<JSGlobalObject>::cast(holder());
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(
- Handle<JSObject> holder, Handle<Name> name, FieldIndex field,
- Representation representation) {
- Register reg = Frontend(receiver(), holder, name);
- GenerateLoadField(reg, holder, field, representation);
+ Handle<Name> name, FieldIndex field, Representation representation) {
+ Register reg = Frontend(receiver(), name);
+ GenerateLoadField(reg, field, representation);
return GetCode(kind(), Code::FAST, name);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(
- Handle<JSObject> holder, Handle<Name> name, Handle<Object> value) {
- Frontend(receiver(), holder, name);
+ Handle<Name> name, Handle<Object> value) {
+ Frontend(receiver(), name);
GenerateLoadConstant(value);
return GetCode(kind(), Code::FAST, name);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
- Handle<JSObject> holder, Handle<Name> name,
- Handle<ExecutableAccessorInfo> callback) {
- Register reg = CallbackFrontend(receiver(), holder, name, callback);
+ Handle<Name> name, Handle<ExecutableAccessorInfo> callback) {
+ Register reg = CallbackFrontend(receiver(), name, callback);
GenerateLoadCallback(reg, callback);
return GetCode(kind(), Code::FAST, name);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
- Handle<JSObject> holder, Handle<Name> name,
- const CallOptimization& call_optimization) {
+ Handle<Name> name, const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call());
Handle<JSFunction> callback = call_optimization.constant_function();
- CallbackFrontend(receiver(), holder, name, callback);
+ CallbackFrontend(receiver(), name, callback);
Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate());
GenerateFastApiCall(
masm(), call_optimization, receiver_map,
Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
- Handle<JSObject> holder, Handle<Name> name) {
+ Handle<Name> name) {
// Perform a lookup after the interceptor.
LookupResult lookup(isolate());
- holder->LookupOwnRealNamedProperty(name, &lookup);
+ holder()->LookupOwnRealNamedProperty(name, &lookup);
if (!lookup.IsFound()) {
- PrototypeIterator iter(holder->GetIsolate(), holder);
+ PrototypeIterator iter(holder()->GetIsolate(), holder());
if (!iter.IsAtEnd()) {
PrototypeIterator::GetCurrent(iter)->Lookup(name, &lookup);
}
}
- Register reg = Frontend(receiver(), holder, name);
+ Register reg = Frontend(receiver(), name);
// TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer.
- GenerateLoadInterceptor(reg, holder, &lookup, name);
+ GenerateLoadInterceptor(reg, &lookup, name);
return GetCode(kind(), Code::FAST, name);
}
void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor(
- Register interceptor_reg, Handle<JSObject> interceptor_holder,
- Handle<Name> name, LookupResult* lookup) {
- Handle<JSObject> holder(lookup->holder());
+ Register interceptor_reg, Handle<Name> name, LookupResult* lookup) {
+ Handle<JSObject> real_named_property_holder(lookup->holder());
if (lookup->IsField()) {
FieldIndex field = lookup->GetFieldIndex();
- if (interceptor_holder.is_identical_to(holder)) {
- GenerateLoadField(
- interceptor_reg, holder, field, lookup->representation());
+ if (holder().is_identical_to(real_named_property_holder)) {
+ GenerateLoadField(interceptor_reg, field, lookup->representation());
} else {
- // We found FIELD property in prototype chain of interceptor's holder.
- // Retrieve a field from field's holder.
- set_type_for_object(interceptor_holder);
- Register reg = Frontend(interceptor_reg, holder, name);
- GenerateLoadField(
- reg, holder, field, lookup->representation());
+ set_type_for_object(holder());
+ set_holder(real_named_property_holder);
+ Register reg = Frontend(interceptor_reg, name);
+ GenerateLoadField(reg, field, lookup->representation());
}
} else {
- // We found CALLBACKS property in prototype chain of interceptor's
- // holder.
+ // We found CALLBACKS property in prototype chain of interceptor's holder.
ASSERT(lookup->type() == CALLBACKS);
Handle<ExecutableAccessorInfo> callback(
ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
ASSERT(callback->getter() != NULL);
- set_type_for_object(interceptor_holder);
- Register reg = CallbackFrontend(interceptor_reg, holder, name, callback);
+ set_type_for_object(holder());
+ set_holder(real_named_property_holder);
+ Register reg = CallbackFrontend(interceptor_reg, name, callback);
GenerateLoadCallback(reg, callback);
}
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter(
- Handle<JSObject> holder, Handle<Name> name, Handle<JSFunction> getter) {
- Frontend(receiver(), holder, name);
+ Handle<Name> name, Handle<JSFunction> getter) {
+ Frontend(receiver(), name);
GenerateLoadViaGetter(masm(), type(), receiver(), getter);
return GetCode(kind(), Code::FAST, name);
}
+// TODO(verwaest): Cleanup. holder() is actually the receiver.
Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
- Handle<JSObject> object, LookupResult* lookup, Handle<Map> transition,
- Handle<Name> name) {
+ LookupResult* lookup, Handle<Map> transition, Handle<Name> name) {
Label miss, slow;
// Ensure no transitions to deprecated maps are followed.
__ CheckMapDeprecated(transition, scratch1(), &miss);
// Check that we are allowed to write this.
- PrototypeIterator iter(object->GetIsolate(), object);
- if (!iter.IsAtEnd()) {
- Handle<JSObject> holder;
- // holder == object indicates that no property was found.
- if (lookup->holder() != *object) {
- holder = Handle<JSObject>(lookup->holder());
- } else {
- // Find the top object.
- do {
- holder = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
- iter.Advance();
- } while (!iter.IsAtEnd());
- }
+ bool is_nonexistent = holder()->map() == transition->GetBackPointer();
+ if (is_nonexistent) {
+ // Find the top object.
+ Handle<JSObject> last;
+ PrototypeIterator iter(isolate(), holder());
+ do {
+ last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
+ iter.Advance();
+ } while (!iter.IsAtEnd());
+ set_holder(last);
+ }
- Register holder_reg = FrontendHeader(receiver(), holder, name, &miss);
+ Register holder_reg = FrontendHeader(receiver(), 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
- // holder.
- if (lookup->holder() == *object) {
- GenerateNegativeHolderLookup(masm(), holder, holder_reg, 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
+ // holder.
+ if (is_nonexistent) {
+ GenerateNegativeHolderLookup(masm(), holder(), holder_reg, name, &miss);
}
GenerateStoreTransition(masm(),
- object,
lookup,
transition,
name,
}
-Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(
- Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) {
+Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupResult* lookup,
+ Handle<Name> name) {
Label miss;
- FrontendHeader(receiver(), object, name, &miss);
+ FrontendHeader(receiver(), name, &miss);
// Generate store field code.
- GenerateStoreField(masm(),
- object,
- lookup,
- receiver(), this->name(), value(), scratch1(), scratch2(),
- &miss);
+ GenerateStoreField(masm(), holder(), lookup, receiver(), this->name(),
+ value(), scratch1(), scratch2(), &miss);
// Handle store cache miss.
__ bind(&miss);
Handle<Code> NamedStoreHandlerCompiler::CompileStoreArrayLength(
- Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) {
+ LookupResult* lookup, Handle<Name> name) {
// This accepts as a receiver anything JSArray::SetElementsLength accepts
// (currently anything except for external arrays which means anything with
// elements of FixedArray type). Value must be a number, but only smis are
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
- Handle<JSFunction> setter) {
- Frontend(receiver(), holder, name);
+ Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) {
+ Frontend(receiver(), name);
GenerateStoreViaSetter(masm(), type(), receiver(), setter);
return GetCode(kind(), Code::FAST, name);
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
+ Handle<JSObject> object, Handle<Name> name,
const CallOptimization& call_optimization) {
- Frontend(receiver(), holder, name);
+ Frontend(receiver(), name);
Register values[] = { value() };
GenerateFastApiCall(
masm(), call_optimization, handle(object->map()),
protected:
PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind,
- Handle<HeapType> type, CacheHolderFlag cache_holder)
- : PropertyAccessCompiler(isolate, kind, cache_holder), type_(type) {}
+ Handle<HeapType> type, Handle<JSObject> holder,
+ CacheHolderFlag cache_holder)
+ : PropertyAccessCompiler(isolate, kind, cache_holder),
+ type_(type),
+ holder_(holder) {}
virtual ~PropertyHandlerCompiler() {}
- virtual Register FrontendHeader(Register object_reg, Handle<JSObject> holder,
- Handle<Name> name, Label* miss) {
+ virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
+ Label* miss) {
UNREACHABLE();
return receiver();
}
virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
- Register Frontend(Register object_reg, Handle<JSObject> holder,
- Handle<Name> name);
+ Register Frontend(Register object_reg, Handle<Name> name);
// TODO(verwaest): Make non-static.
static void GenerateFastApiCall(MacroAssembler* masm,
// 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(Register object_reg, Handle<JSObject> holder,
- Register holder_reg, Register scratch1,
- Register scratch2, Handle<Name> name, Label* miss,
+ Register CheckPrototypes(Register object_reg, Register holder_reg,
+ Register scratch1, Register scratch2,
+ Handle<Name> name, Label* miss,
PrototypeCheckType check = CHECK_ALL_MAPS);
Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name);
void set_type_for_object(Handle<Object> object) {
type_ = IC::CurrentTypeOf(object, isolate());
}
+ void set_holder(Handle<JSObject> holder) { holder_ = holder; }
Handle<HeapType> type() const { return type_; }
+ Handle<JSObject> holder() const { return holder_; }
private:
Handle<HeapType> type_;
+ Handle<JSObject> holder_;
};
class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
public:
NamedLoadHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
+ Handle<JSObject> holder,
CacheHolderFlag cache_holder)
- : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, cache_holder) {}
+ : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, holder,
+ cache_holder) {}
virtual ~NamedLoadHandlerCompiler() {}
- Handle<Code> CompileLoadField(Handle<JSObject> holder, Handle<Name> name,
- FieldIndex index,
+ Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index,
Representation representation);
- Handle<Code> CompileLoadCallback(Handle<JSObject> holder, Handle<Name> name,
+ Handle<Code> CompileLoadCallback(Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
- Handle<Code> CompileLoadCallback(Handle<JSObject> holder, Handle<Name> name,
+ Handle<Code> CompileLoadCallback(Handle<Name> name,
const CallOptimization& call_optimization);
- Handle<Code> CompileLoadConstant(Handle<JSObject> holder, Handle<Name> name,
- Handle<Object> value);
+ Handle<Code> CompileLoadConstant(Handle<Name> name, Handle<Object> value);
- Handle<Code> CompileLoadInterceptor(Handle<JSObject> holder,
- Handle<Name> name);
+ Handle<Code> CompileLoadInterceptor(Handle<Name> name);
- Handle<Code> CompileLoadViaGetter(Handle<JSObject> holder, Handle<Name> name,
+ Handle<Code> CompileLoadViaGetter(Handle<Name> name,
Handle<JSFunction> getter);
- Handle<Code> CompileLoadGlobal(Handle<GlobalObject> holder,
- Handle<PropertyCell> cell, Handle<Name> name,
+ Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
bool is_dont_delete);
+ // Static interface
static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Handle<HeapType> type);
static const int kInterceptorArgsLength = 4;
protected:
- virtual Register FrontendHeader(Register object_reg, Handle<JSObject> holder,
- Handle<Name> name, Label* miss);
+ virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
+ Label* miss);
virtual void FrontendFooter(Handle<Name> name, Label* miss);
private:
- Register CallbackFrontend(Register object_reg, Handle<JSObject> holder,
- Handle<Name> name, Handle<Object> callback);
- Handle<Code> CompileLoadNonexistent(Handle<JSObject> last, Handle<Name> name);
- void NonexistentFrontend(Handle<JSObject> last, Handle<Name> name);
+ Register CallbackFrontend(Register object_reg, Handle<Name> name,
+ Handle<Object> callback);
+ Handle<Code> CompileLoadNonexistent(Handle<Name> name);
+ void NonexistentFrontend(Handle<Name> name);
void GenerateLoadField(Register reg,
- Handle<JSObject> holder,
FieldIndex field,
Representation representation);
void GenerateLoadConstant(Handle<Object> value);
void GenerateLoadCallback(const CallOptimization& call_optimization,
Handle<Map> receiver_map);
void GenerateLoadInterceptor(Register holder_reg,
- Handle<JSObject> holder,
LookupResult* lookup,
Handle<Name> name);
void GenerateLoadPostInterceptor(Register reg,
- Handle<JSObject> interceptor_holder,
Handle<Name> name,
LookupResult* lookup);
class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
public:
- explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type)
- : PropertyHandlerCompiler(isolate, Code::STORE_IC, type,
+ explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
+ Handle<JSObject> holder)
+ : PropertyHandlerCompiler(isolate, Code::STORE_IC, type, holder,
kCacheOnReceiver) {}
virtual ~NamedStoreHandlerCompiler() {}
- Handle<Code> CompileStoreTransition(Handle<JSObject> object,
- LookupResult* lookup,
+ Handle<Code> CompileStoreTransition(LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name);
- Handle<Code> CompileStoreField(Handle<JSObject> object,
- LookupResult* lookup,
- Handle<Name> name);
+ Handle<Code> CompileStoreField(LookupResult* lookup, Handle<Name> name);
- Handle<Code> CompileStoreArrayLength(Handle<JSObject> object,
- LookupResult* lookup,
- Handle<Name> name);
+ Handle<Code> CompileStoreArrayLength(LookupResult* lookup, Handle<Name> name);
- Handle<Code> CompileStoreCallback(Handle<JSObject> object,
- Handle<JSObject> holder, Handle<Name> name,
+ Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
- Handle<Code> CompileStoreCallback(Handle<JSObject> object,
- Handle<JSObject> holder, Handle<Name> name,
+ Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
const CallOptimization& call_optimization);
- Handle<Code> CompileStoreViaSetter(Handle<JSObject> object,
- Handle<JSObject> holder, Handle<Name> name,
+ Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
Handle<JSFunction> setter);
- Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
- Handle<Name> name);
+ Handle<Code> CompileStoreInterceptor(Handle<Name> name);
static void GenerateStoreViaSetter(MacroAssembler* masm,
}
protected:
- virtual Register FrontendHeader(Register object_reg, Handle<JSObject> holder,
- Handle<Name> name, Label* miss);
+ virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
+ Label* miss);
virtual void FrontendFooter(Handle<Name> name, Label* miss);
void GenerateRestoreName(MacroAssembler* masm, Label* label,
Label* miss);
void GenerateStoreTransition(MacroAssembler* masm,
- Handle<JSObject> object,
LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
public:
explicit ElementHandlerCompiler(Isolate* isolate)
: PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
- Handle<HeapType>::null(), kCacheOnReceiver) {}
+ Handle<HeapType>::null(),
+ Handle<JSObject>::null(), kCacheOnReceiver) {}
virtual ~ElementHandlerCompiler() {}
// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful.
void NamedStoreHandlerCompiler::GenerateStoreTransition(
- MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup,
- Handle<Map> transition, Handle<Name> name, Register receiver_reg,
- Register storage_reg, Register value_reg, Register scratch1,
- Register scratch2, Register unused, Label* miss_label, Label* slow) {
+ MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition,
+ Handle<Name> name, Register receiver_reg, Register storage_reg,
+ Register value_reg, Register scratch1, Register scratch2, Register unused,
+ Label* miss_label, Label* slow) {
int descriptor = transition->LastAdded();
DescriptorArray* descriptors = transition->instance_descriptors();
PropertyDetails details = descriptors->GetDetails(descriptor);
__ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
}
- // Stub never generated for non-global objects that require access
- // checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+ // Stub never generated for objects that require access checks.
+ ASSERT(!transition->is_access_check_needed());
// Perform map transition for the receiver if necessary.
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.
// We jump to a runtime call that extends the properties array.
__ PopReturnAddressTo(scratch1);
// 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
// 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.
SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
if (index < 0) {
// 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()) {
__ movp(FieldOperand(receiver_reg, offset), storage_reg);
} else {
Register PropertyHandlerCompiler::CheckPrototypes(
- Register object_reg, Handle<JSObject> holder, Register holder_reg,
- Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ Register object_reg, Register holder_reg, Register scratch1,
+ Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
}
Handle<JSObject> prototype = Handle<JSObject>::null();
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
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
- Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
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(scratch3()));
ASSERT(!reg.is(scratch4()));
void NamedLoadHandlerCompiler::GenerateLoadField(
- Register reg, Handle<JSObject> holder, FieldIndex field,
- Representation representation) {
+ Register reg, FieldIndex field, Representation representation) {
if (!reg.is(receiver())) __ movp(receiver(), reg);
LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
-void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<JSObject> interceptor_holder,
- LookupResult* lookup, Handle<Name> name) {
- ASSERT(interceptor_holder->HasNamedInterceptor());
- ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
+void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
+ LookupResult* lookup,
+ Handle<Name> name) {
+ ASSERT(holder()->HasNamedInterceptor());
+ ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added
// 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,
// 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) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
// interceptor's holder has been compiled before (see a caller
// of this method.)
CompileCallLoadPropertyWithInterceptor(
- masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ masm(), receiver(), holder_reg, this->name(), holder(),
IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's
// Leave the internal frame.
}
- GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
+ GenerateLoadPostInterceptor(holder_reg, name, lookup);
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
__ PopReturnAddressTo(scratch2());
- PushInterceptorArguments(masm(), receiver(), holder_reg,
- this->name(), interceptor_holder);
+ PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
+ holder());
__ PushReturnAddressFrom(scratch2());
ExternalReference ref = ExternalReference(
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
+ Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg = Frontend(receiver(), holder, name);
+ Register holder_reg = Frontend(receiver(), name);
__ PopReturnAddressTo(scratch1());
__ Push(receiver());
Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
- Handle<JSObject> object, Handle<Name> name) {
+ Handle<Name> name) {
__ PopReturnAddressTo(scratch1());
__ Push(receiver());
__ Push(this->name());
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(last, name);
+ Handle<Name> name) {
+ NonexistentFrontend(name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
- bool is_dont_delete) {
+ Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Label miss;
- FrontendHeader(receiver(), global, name, &miss);
+ FrontendHeader(receiver(), name, &miss);
// Get the value from the cell.
Register result = StoreIC::ValueRegister();