Register PropertyHandlerCompiler::CheckPrototypes(
- Handle<HeapType> type, Register object_reg, Handle<JSObject> holder,
- Register holder_reg, Register scratch1, Register scratch2,
- Handle<Name> name, Label* miss, PrototypeCheckType check) {
- Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
+ Register object_reg, Handle<JSObject> holder, Register holder_reg,
+ Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ PrototypeCheckType check) {
+ Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
// Make sure there's no overlap between holder and object registers.
ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) {
- current = Handle<JSObject>::cast(type->AsConstant()->Value());
+ if (type()->IsConstant()) {
+ current = Handle<JSObject>::cast(type()->AsConstant()->Value());
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
}
-Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type,
- Register object_reg,
+Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
Label miss;
- Register reg = FrontendHeader(type, object_reg, holder, name, &miss);
+ Register reg = FrontendHeader(object_reg, holder, name, &miss);
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
ASSERT(!reg.is(scratch2()));
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<Object> object,
- Handle<JSObject> interceptor_holder, LookupResult* lookup,
- Handle<Name> name) {
+ Register holder_reg, Handle<JSObject> interceptor_holder,
+ LookupResult* lookup, Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&
lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
- ExecutableAccessorInfo* callback =
- ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
- compile_followup_inline = callback->getter() != NULL &&
- callback->IsCompatibleReceiver(*object);
+ Handle<ExecutableAccessorInfo> callback(
+ ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
+ compile_followup_inline =
+ callback->getter() != NULL &&
+ ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback,
+ type());
}
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg =
- Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
+ Register holder_reg = Frontend(receiver(), holder, name);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(type, last, name);
+ Handle<JSObject> last, Handle<Name> name) {
+ NonexistentFrontend(last, name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<HeapType> type, Handle<GlobalObject> global,
- Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
+ Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
+ bool is_dont_delete) {
Label miss;
- FrontendHeader(type, receiver(), global, name, &miss);
+ FrontendHeader(receiver(), global, name, &miss);
// Get the value from the cell.
- __ mov(r3, Operand(cell));
- __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset));
+ Register result = StoreIC::ValueRegister();
+ __ mov(result, Operand(cell));
+ __ ldr(result, FieldMemOperand(result, Cell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
- __ cmp(r4, ip);
+ __ cmp(result, ip);
__ b(eq, &miss);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
- __ mov(r0, r4);
__ Ret();
FrontendFooter(name, &miss);
Register PropertyHandlerCompiler::CheckPrototypes(
- Handle<HeapType> type, Register object_reg, Handle<JSObject> holder,
- Register holder_reg, Register scratch1, Register scratch2,
- Handle<Name> name, Label* miss, PrototypeCheckType check) {
- Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
+ Register object_reg, Handle<JSObject> holder, Register holder_reg,
+ Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ PrototypeCheckType check) {
+ Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
// object_reg and holder_reg registers can alias.
ASSERT(!AreAliased(object_reg, scratch1, scratch2));
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) {
- current = Handle<JSObject>::cast(type->AsConstant()->Value());
+ if (type()->IsConstant()) {
+ current = Handle<JSObject>::cast(type()->AsConstant()->Value());
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
}
-Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type,
- Register object_reg,
+Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
Label miss;
- Register reg = FrontendHeader(type, object_reg, holder, name, &miss);
+ Register reg = FrontendHeader(object_reg, holder, name, &miss);
// FrontendHeader can return its result into scratch1() so do not
// use it.
Register scratch2 = this->scratch2();
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<Object> object,
- Handle<JSObject> interceptor_holder, LookupResult* lookup,
- Handle<Name> name) {
+ Register holder_reg, Handle<JSObject> interceptor_holder,
+ LookupResult* lookup, Handle<Name> name) {
ASSERT(!AreAliased(receiver(), this->name(),
scratch1(), scratch2(), scratch3()));
ASSERT(interceptor_holder->HasNamedInterceptor());
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&
lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
- ExecutableAccessorInfo* callback =
- ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
- compile_followup_inline = callback->getter() != NULL &&
- callback->IsCompatibleReceiver(*object);
+ Handle<ExecutableAccessorInfo> callback(
+ ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
+ compile_followup_inline =
+ callback->getter() != NULL &&
+ ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback,
+ type());
}
}
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback");
- Register holder_reg =
- Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
+ Register holder_reg = Frontend(receiver(), holder, name);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(type, last, name);
+ Handle<JSObject> last, Handle<Name> name) {
+ NonexistentFrontend(last, name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<HeapType> type, Handle<GlobalObject> global,
- Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
+ Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
+ bool is_dont_delete) {
Label miss;
- FrontendHeader(type, receiver(), global, name, &miss);
+ FrontendHeader(receiver(), global, name, &miss);
// Get the value from the cell.
- __ Mov(x3, Operand(cell));
- __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset));
+ Register result = StoreIC::ValueRegister();
+ __ Mov(result, Operand(cell));
+ __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
- __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss);
+ __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3);
- __ Mov(x0, x4);
__ Ret();
FrontendFooter(name, &miss);
Register PropertyHandlerCompiler::CheckPrototypes(
- Handle<HeapType> type, Register object_reg, Handle<JSObject> holder,
- Register holder_reg, Register scratch1, Register scratch2,
- Handle<Name> name, Label* miss, PrototypeCheckType check) {
- Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
+ Register object_reg, Handle<JSObject> holder, Register holder_reg,
+ Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ PrototypeCheckType check) {
+ Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
// Make sure there's no overlap between holder and object registers.
ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) current =
- Handle<JSObject>::cast(type->AsConstant()->Value());
+ if (type()->IsConstant())
+ 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());
}
-Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type,
- Register object_reg,
+Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
Label miss;
- Register reg = FrontendHeader(type, object_reg, holder, name, &miss);
+ Register reg = FrontendHeader(object_reg, holder, name, &miss);
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
ASSERT(!reg.is(scratch2()));
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<Object> object,
- Handle<JSObject> interceptor_holder, LookupResult* lookup,
- Handle<Name> name) {
+ Register holder_reg, Handle<JSObject> interceptor_holder,
+ LookupResult* lookup, Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&
lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
- ExecutableAccessorInfo* callback =
- ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
- compile_followup_inline = callback->getter() != NULL &&
- callback->IsCompatibleReceiver(*object);
+ Handle<ExecutableAccessorInfo> callback(
+ ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
+ compile_followup_inline =
+ callback->getter() != NULL &&
+ ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback,
+ type());
}
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg =
- Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
+ Register holder_reg = Frontend(receiver(), holder, name);
__ pop(scratch1()); // remove the return address
__ push(receiver());
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(type, last, name);
+ Handle<JSObject> last, Handle<Name> name) {
+ NonexistentFrontend(last, name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<HeapType> type, Handle<GlobalObject> global,
- Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
+ Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
+ bool is_dont_delete) {
Label miss;
- FrontendHeader(type, receiver(), global, name, &miss);
+ FrontendHeader(receiver(), global, name, &miss);
// Get the value from the cell.
+ Register result = StoreIC::ValueRegister();
if (masm()->serializer_enabled()) {
- __ mov(eax, Immediate(cell));
- __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset));
+ __ mov(result, Immediate(cell));
+ __ mov(result, FieldOperand(result, PropertyCell::kValueOffset));
} else {
- __ mov(eax, Operand::ForCell(cell));
+ __ mov(result, Operand::ForCell(cell));
}
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
- __ cmp(eax, factory()->the_hole_value());
+ __ cmp(result, factory()->the_hole_value());
__ j(equal, &miss);
} else if (FLAG_debug_code) {
- __ cmp(eax, factory()->the_hole_value());
+ __ cmp(result, factory()->the_hole_value());
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
Handle<HeapType> type = receiver_type();
Handle<JSObject> holder(lookup->holder());
bool receiver_is_holder = object.is_identical_to(holder);
- NamedLoadHandlerCompiler compiler(isolate(), cache_holder);
+ NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), cache_holder);
switch (lookup->type()) {
case FIELD: {
if (receiver_is_holder) {
return SimpleFieldLoad(field);
}
- return compiler.CompileLoadField(
- type, holder, name, field, lookup->representation());
+ return compiler.CompileLoadField(holder, name, field,
+ lookup->representation());
}
case CONSTANT: {
Handle<Object> constant(lookup->GetConstant(), isolate());
- return compiler.CompileLoadConstant(type, holder, name, constant);
+ return compiler.CompileLoadConstant(holder, name, constant);
}
case NORMAL:
if (kind() != Code::LOAD_IC) break;
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
Handle<PropertyCell> cell(
global->GetPropertyCell(lookup), isolate());
- Handle<Code> code = compiler.CompileLoadGlobal(
- type, global, cell, name, lookup->IsDontDelete());
+ Handle<Code> code = compiler.CompileLoadGlobal(global, cell, name,
+ lookup->IsDontDelete());
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
CacheHolderFlag flag;
Handle<Map> stub_holder_map =
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->getter()) == 0) break;
- if (!info->IsCompatibleReceiver(*object)) break;
- return compiler.CompileLoadCallback(type, holder, name, info);
+ if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
+ type)) {
+ break;
+ }
+ return compiler.CompileLoadCallback(holder, name, info);
} else if (callback->IsAccessorPair()) {
Handle<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(
- type, holder, name, call_optimization);
+ return compiler.CompileLoadCallback(holder, name, call_optimization);
}
- return compiler.CompileLoadViaGetter(type, holder, name, function);
+ return compiler.CompileLoadViaGetter(holder, name, function);
}
// TODO(dcarney): Handle correctly.
ASSERT(callback->IsDeclaredAccessorInfo());
}
case INTERCEPTOR:
ASSERT(HasInterceptorGetter(*holder));
- return compiler.CompileLoadInterceptor(type, holder, name);
+ return compiler.CompileLoadInterceptor(holder, name);
default:
break;
}
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<JSObject> holder(lookup->holder());
- NamedStoreHandlerCompiler compiler(isolate());
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_type());
if (lookup->IsTransition()) {
// Explicitly pass in the receiver map since LookupForWrite may have
Handle<ExecutableAccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->setter()) == 0) break;
if (!holder->HasFastProperties()) break;
- if (!info->IsCompatibleReceiver(*receiver)) break;
+ if (!ExecutableAccessorInfo::IsCompatibleReceiverType(
+ isolate(), info, receiver_type())) {
+ break;
+ }
return compiler.CompileStoreCallback(receiver, holder, name, info);
} else if (callback->IsAccessorPair()) {
Handle<Object> setter(
bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
- Object* function_template = expected_receiver_type();
- if (!function_template->IsFunctionTemplateInfo()) return true;
- return FunctionTemplateInfo::cast(function_template)->IsTemplateFor(receiver);
+ if (!HasExpectedReceiverType()) return true;
+ if (!receiver->IsJSObject()) return false;
+ return FunctionTemplateInfo::cast(expected_receiver_type())
+ ->IsTemplateFor(JSObject::cast(receiver)->map());
}
ASSERT(!structure->IsForeign());
// api style callbacks.
if (structure->IsAccessorInfo()) {
- Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure);
- if (!accessor_info->IsCompatibleReceiver(*receiver)) {
+ Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
+ if (!info->IsCompatibleReceiver(*receiver)) {
Handle<Object> args[2] = { name, receiver };
Handle<Object> error =
isolate->factory()->NewTypeError("incompatible_method_receiver",
}
+bool AccessorInfo::IsCompatibleReceiverType(Isolate* isolate,
+ Handle<AccessorInfo> info,
+ Handle<HeapType> type) {
+ if (!info->HasExpectedReceiverType()) return true;
+ Handle<Map> map = IC::TypeToMap(*type, isolate);
+ if (!map->IsJSObjectMap()) return false;
+ return FunctionTemplateInfo::cast(info->expected_receiver_type())
+ ->IsTemplateFor(*map);
+}
+
+
MaybeHandle<Object> Object::SetPropertyWithAccessor(
Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
Handle<JSObject> holder, Handle<Object> structure, StrictMode strict_mode) {
// Don't call executable accessor setters with non-JSObject receivers.
if (!receiver->IsJSObject()) return value;
// api style callbacks
- ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
- if (!data->IsCompatibleReceiver(*receiver)) {
+ ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure);
+ if (!info->IsCompatibleReceiver(*receiver)) {
Handle<Object> args[2] = { name, receiver };
Handle<Object> error =
isolate->factory()->NewTypeError("incompatible_method_receiver",
}
// TODO(rossberg): Support symbols in the API.
if (name->IsSymbol()) return value;
- Object* call_obj = data->setter();
+ Object* call_obj = info->setter();
v8::AccessorSetterCallback call_fun =
v8::ToCData<v8::AccessorSetterCallback>(call_obj);
if (call_fun == NULL) return value;
Handle<String> key = Handle<String>::cast(name);
LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
- PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
+ PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
args.Call(call_fun,
v8::Utils::ToLocal(key),
v8::Utils::ToLocal(value));
inline void set_property_attributes(PropertyAttributes attributes);
// Checks whether the given receiver is compatible with this accessor.
+ static bool IsCompatibleReceiverType(Isolate* isolate,
+ Handle<AccessorInfo> info,
+ Handle<HeapType> type);
inline bool IsCompatibleReceiver(Object* receiver);
DECLARE_CAST(AccessorInfo)
static const int kSize = kExpectedReceiverTypeOffset + kPointerSize;
private:
+ inline bool HasExpectedReceiverType() {
+ return expected_receiver_type()->IsFunctionTemplateInfo();
+ }
// Bit positions in flag.
static const int kAllCanReadBit = 0;
static const int kAllCanWriteBit = 1;
cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST);
if (!handler.is_null()) return handler;
- NamedLoadHandlerCompiler compiler(isolate, flag);
- handler = compiler.CompileLoadNonexistent(type, last, cache_name);
+ NamedLoadHandlerCompiler compiler(isolate, type, flag);
+ handler = compiler.CompileLoadNonexistent(last, cache_name);
Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
return handler;
}
RUNTIME_FUNCTION(StoreCallbackProperty) {
- JSObject* receiver = JSObject::cast(args[0]);
- JSObject* holder = JSObject::cast(args[1]);
- ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[2]);
+ Handle<JSObject> receiver = args.at<JSObject>(0);
+ Handle<JSObject> holder = args.at<JSObject>(1);
+ Handle<ExecutableAccessorInfo> callback = args.at<ExecutableAccessorInfo>(2);
+ Handle<Name> name = args.at<Name>(3);
+ Handle<Object> value = args.at<Object>(4);
+ HandleScope scope(isolate);
+
+ ASSERT(callback->IsCompatibleReceiver(*receiver));
+
Address setter_address = v8::ToCData<Address>(callback->setter());
v8::AccessorSetterCallback fun =
FUNCTION_CAST<v8::AccessorSetterCallback>(setter_address);
ASSERT(fun != NULL);
- ASSERT(callback->IsCompatibleReceiver(receiver));
- Handle<Name> name = args.at<Name>(3);
- Handle<Object> value = args.at<Object>(4);
- HandleScope scope(isolate);
// TODO(rossberg): Support symbols in the API.
if (name->IsSymbol()) return *value;
Handle<String> str = Handle<String>::cast(name);
- LOG(isolate, ApiNamedPropertyAccess("store", receiver, *name));
- PropertyCallbackArguments
- custom_args(isolate, callback->data(), receiver, holder);
+ LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name));
+ PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
+ *holder);
custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value));
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *value;
#define __ ACCESS_MASM(masm())
-Register NamedLoadHandlerCompiler::FrontendHeader(Handle<HeapType> type,
- Register object_reg,
+Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
PrototypeCheckType check_type = CHECK_ALL_MAPS;
int function_index = -1;
- if (type->Is(HeapType::String())) {
+ if (type()->Is(HeapType::String())) {
function_index = Context::STRING_FUNCTION_INDEX;
- } else if (type->Is(HeapType::Symbol())) {
+ } else if (type()->Is(HeapType::Symbol())) {
function_index = Context::SYMBOL_FUNCTION_INDEX;
- } else if (type->Is(HeapType::Number())) {
+ } else if (type()->Is(HeapType::Number())) {
function_index = Context::NUMBER_FUNCTION_INDEX;
- } else if (type->Is(HeapType::Boolean())) {
+ } else if (type()->Is(HeapType::Boolean())) {
function_index = Context::BOOLEAN_FUNCTION_INDEX;
} else {
check_type = SKIP_RECEIVER;
masm(), function_index, scratch1(), miss);
Object* function = isolate()->native_context()->get(function_index);
Object* prototype = JSFunction::cast(function)->instance_prototype();
- type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate());
+ set_type_for_object(handle(prototype, isolate()));
object_reg = scratch1();
}
// Check that the maps starting from the prototype haven't changed.
- return CheckPrototypes(
- type, object_reg, holder, scratch1(), scratch2(), scratch3(),
- name, miss, check_type);
+ return CheckPrototypes(object_reg, holder, scratch1(), scratch2(), scratch3(),
+ name, miss, check_type);
}
// Frontend for store uses the name register. It has to be restored before a
// miss.
-Register NamedStoreHandlerCompiler::FrontendHeader(Handle<HeapType> type,
- Register object_reg,
+Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
- return CheckPrototypes(type, object_reg, holder, this->name(),
- scratch1(), scratch2(), name, miss, SKIP_RECEIVER);
+ return CheckPrototypes(object_reg, holder, this->name(), scratch1(),
+ scratch2(), name, miss, SKIP_RECEIVER);
}
}
-Register PropertyHandlerCompiler::Frontend(Handle<HeapType> type,
- Register object_reg,
+Register PropertyHandlerCompiler::Frontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name) {
Label miss;
- Register reg = FrontendHeader(type, object_reg, holder, name, &miss);
+ Register reg = FrontendHeader(object_reg, holder, name, &miss);
FrontendFooter(name, &miss);
return reg;
}
-void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<HeapType> type,
- Handle<JSObject> last,
+void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<JSObject> last,
Handle<Name> name) {
Label miss;
Handle<Map> last_map;
if (last.is_null()) {
holder = receiver();
- last_map = IC::TypeToMap(*type, isolate());
+ last_map = IC::TypeToMap(*type(), isolate());
// If |type| has null as its prototype, |last| is Handle<JSObject>::null().
ASSERT(last_map->prototype() == isolate()->heap()->null_value());
} else {
- holder = FrontendHeader(type, receiver(), last, name, &miss);
+ holder = FrontendHeader(receiver(), last, name, &miss);
last_map = handle(last->map());
}
// If the last object in the prototype chain is a global object,
// check that the global property cell is empty.
if (last_map->IsJSGlobalObjectMap()) {
- Handle<JSGlobalObject> global = last.is_null()
- ? Handle<JSGlobalObject>::cast(type->AsConstant()->Value())
- : Handle<JSGlobalObject>::cast(last);
+ Handle<JSGlobalObject> global =
+ last.is_null()
+ ? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value())
+ : Handle<JSGlobalObject>::cast(last);
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(
- Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name,
- FieldIndex field, Representation representation) {
- Register reg = Frontend(type, receiver(), holder, name);
+ Handle<JSObject> holder, Handle<Name> name, FieldIndex field,
+ Representation representation) {
+ Register reg = Frontend(receiver(), holder, name);
GenerateLoadField(reg, holder, field, representation);
return GetCode(kind(), Code::FAST, name);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(
- Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name,
- Handle<Object> value) {
- Frontend(type, receiver(), holder, name);
+ Handle<JSObject> holder, Handle<Name> name, Handle<Object> value) {
+ Frontend(receiver(), holder, name);
GenerateLoadConstant(value);
return GetCode(kind(), Code::FAST, name);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
- Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name,
+ Handle<JSObject> holder, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register reg = CallbackFrontend(type, receiver(), holder, name, callback);
+ Register reg = CallbackFrontend(receiver(), holder, name, callback);
GenerateLoadCallback(reg, callback);
return GetCode(kind(), Code::FAST, name);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
- Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name,
+ Handle<JSObject> holder, Handle<Name> name,
const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call());
Handle<JSFunction> callback = call_optimization.constant_function();
- CallbackFrontend(type, receiver(), holder, name, callback);
- Handle<Map>receiver_map = IC::TypeToMap(*type, isolate());
+ CallbackFrontend(receiver(), holder, name, callback);
+ Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate());
GenerateFastApiCall(
masm(), call_optimization, receiver_map,
receiver(), scratch1(), false, 0, NULL);
Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
- Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name) {
+ Handle<JSObject> holder, Handle<Name> name) {
// Perform a lookup after the interceptor.
LookupResult lookup(isolate());
holder->LookupOwnRealNamedProperty(name, &lookup);
}
}
- Register reg = Frontend(type, receiver(), holder, name);
+ Register reg = Frontend(receiver(), holder, name);
// TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer.
- GenerateLoadInterceptor(reg, type, holder, &lookup, name);
+ GenerateLoadInterceptor(reg, holder, &lookup, name);
return GetCode(kind(), Code::FAST, name);
}
} else {
// We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder.
- Register reg = Frontend(IC::CurrentTypeOf(interceptor_holder, isolate()),
- interceptor_reg, holder, name);
+ set_type_for_object(interceptor_holder);
+ Register reg = Frontend(interceptor_reg, holder, name);
GenerateLoadField(
reg, holder, field, lookup->representation());
}
ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
ASSERT(callback->getter() != NULL);
- Register reg =
- CallbackFrontend(IC::CurrentTypeOf(interceptor_holder, isolate()),
- interceptor_reg, holder, name, callback);
+ set_type_for_object(interceptor_holder);
+ Register reg = CallbackFrontend(interceptor_reg, holder, name, callback);
GenerateLoadCallback(reg, callback);
}
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter(
- Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name,
- Handle<JSFunction> getter) {
- Frontend(type, receiver(), holder, name);
- GenerateLoadViaGetter(masm(), type, receiver(), getter);
+ Handle<JSObject> holder, Handle<Name> name, Handle<JSFunction> getter) {
+ Frontend(receiver(), holder, name);
+ GenerateLoadViaGetter(masm(), type(), receiver(), getter);
return GetCode(kind(), Code::FAST, name);
}
} while (!iter.IsAtEnd());
}
- Register holder_reg = FrontendHeader(IC::CurrentTypeOf(object, isolate()),
- receiver(), holder, name, &miss);
+ Register holder_reg = FrontendHeader(receiver(), holder, name, &miss);
// If no property was found, and the holder (the last object in the
// prototype chain) is in slow mode, we need to do a negative lookup on the
Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) {
Label miss;
- FrontendHeader(IC::CurrentTypeOf(object, isolate()), receiver(), object, name,
- &miss);
+ FrontendHeader(receiver(), object, name, &miss);
// Generate store field code.
GenerateStoreField(masm(),
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
Handle<JSFunction> setter) {
- Handle<HeapType> type = IC::CurrentTypeOf(object, isolate());
- Frontend(type, receiver(), holder, name);
- GenerateStoreViaSetter(masm(), type, receiver(), setter);
+ Frontend(receiver(), holder, name);
+ GenerateStoreViaSetter(masm(), type(), receiver(), setter);
return GetCode(kind(), Code::FAST, name);
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
const CallOptimization& call_optimization) {
- Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
+ Frontend(receiver(), holder, name);
Register values[] = { value() };
GenerateFastApiCall(
masm(), call_optimization, handle(object->map()),
protected:
PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind,
- CacheHolderFlag cache_holder)
- : PropertyAccessCompiler(isolate, kind, cache_holder) {}
+ Handle<HeapType> type, CacheHolderFlag cache_holder)
+ : PropertyAccessCompiler(isolate, kind, cache_holder), type_(type) {}
virtual ~PropertyHandlerCompiler() {}
- virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg,
- Handle<JSObject> holder, Handle<Name> name,
- Label* miss) {
+ virtual Register FrontendHeader(Register object_reg, Handle<JSObject> holder,
+ Handle<Name> name, Label* miss) {
UNREACHABLE();
return receiver();
}
virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
- Register Frontend(Handle<HeapType> type, Register object_reg,
- Handle<JSObject> holder, Handle<Name> name);
+ Register Frontend(Register object_reg, Handle<JSObject> holder,
+ 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(Handle<HeapType> type,
- Register object_reg,
- Handle<JSObject> holder,
- Register holder_reg,
- Register scratch1,
- Register scratch2,
- Handle<Name> name,
- Label* miss,
+ Register CheckPrototypes(Register object_reg, Handle<JSObject> holder,
+ 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());
+ }
+ Handle<HeapType> type() const { return type_; }
+
+ private:
+ Handle<HeapType> type_;
};
class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
public:
- NamedLoadHandlerCompiler(Isolate* isolate,
- CacheHolderFlag cache_holder = kCacheOnReceiver)
- : PropertyHandlerCompiler(isolate, Code::LOAD_IC, cache_holder) {}
+ NamedLoadHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
+ CacheHolderFlag cache_holder)
+ : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, cache_holder) {}
virtual ~NamedLoadHandlerCompiler() {}
- Handle<Code> CompileLoadField(Handle<HeapType> type,
- Handle<JSObject> holder,
- Handle<Name> name,
+ Handle<Code> CompileLoadField(Handle<JSObject> holder, Handle<Name> name,
FieldIndex index,
Representation representation);
- Handle<Code> CompileLoadCallback(Handle<HeapType> type,
- Handle<JSObject> holder,
- Handle<Name> name,
+ Handle<Code> CompileLoadCallback(Handle<JSObject> holder, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
- Handle<Code> CompileLoadCallback(Handle<HeapType> type,
- Handle<JSObject> holder,
- Handle<Name> name,
+ Handle<Code> CompileLoadCallback(Handle<JSObject> holder, Handle<Name> name,
const CallOptimization& call_optimization);
- Handle<Code> CompileLoadConstant(Handle<HeapType> type,
- Handle<JSObject> holder,
- Handle<Name> name,
+ Handle<Code> CompileLoadConstant(Handle<JSObject> holder, Handle<Name> name,
Handle<Object> value);
- Handle<Code> CompileLoadInterceptor(Handle<HeapType> type,
- Handle<JSObject> holder,
+ Handle<Code> CompileLoadInterceptor(Handle<JSObject> holder,
Handle<Name> name);
- Handle<Code> CompileLoadViaGetter(Handle<HeapType> type,
- Handle<JSObject> holder,
- Handle<Name> name,
+ Handle<Code> CompileLoadViaGetter(Handle<JSObject> holder, Handle<Name> name,
Handle<JSFunction> getter);
+ Handle<Code> CompileLoadGlobal(Handle<GlobalObject> holder,
+ Handle<PropertyCell> cell, Handle<Name> name,
+ bool is_dont_delete);
+
static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Handle<HeapType> type);
- Handle<Code> CompileLoadGlobal(Handle<HeapType> type,
- Handle<GlobalObject> holder,
- Handle<PropertyCell> cell,
- Handle<Name> name,
- bool is_dont_delete);
-
static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type,
Register receiver,
Handle<JSFunction> getter);
static const int kInterceptorArgsLength = 4;
protected:
- virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg,
- Handle<JSObject> holder, Handle<Name> name,
- Label* miss);
+ virtual Register FrontendHeader(Register object_reg, Handle<JSObject> holder,
+ Handle<Name> name, Label* miss);
virtual void FrontendFooter(Handle<Name> name, Label* miss);
private:
- Register CallbackFrontend(Handle<HeapType> type, Register object_reg,
- Handle<JSObject> holder, Handle<Name> name,
- Handle<Object> callback);
- Handle<Code> CompileLoadNonexistent(Handle<HeapType> type,
- Handle<JSObject> last, Handle<Name> name);
- void NonexistentFrontend(Handle<HeapType> type, Handle<JSObject> last,
- Handle<Name> name);
+ 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);
void GenerateLoadField(Register reg,
Handle<JSObject> holder,
void GenerateLoadCallback(const CallOptimization& call_optimization,
Handle<Map> receiver_map);
void GenerateLoadInterceptor(Register holder_reg,
- Handle<Object> object,
Handle<JSObject> holder,
LookupResult* lookup,
Handle<Name> name);
class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
public:
- explicit NamedStoreHandlerCompiler(Isolate* isolate)
- : PropertyHandlerCompiler(isolate, Code::STORE_IC, kCacheOnReceiver) {}
+ explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type)
+ : PropertyHandlerCompiler(isolate, Code::STORE_IC, type,
+ kCacheOnReceiver) {}
virtual ~NamedStoreHandlerCompiler() {}
}
protected:
- virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg,
- Handle<JSObject> holder, Handle<Name> name,
- Label* miss);
+ virtual Register FrontendHeader(Register object_reg, Handle<JSObject> holder,
+ Handle<Name> name, Label* miss);
virtual void FrontendFooter(Handle<Name> name, Label* miss);
void GenerateRestoreName(MacroAssembler* masm, Label* label,
public:
explicit ElementHandlerCompiler(Isolate* isolate)
: PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
- kCacheOnReceiver) {}
+ Handle<HeapType>::null(), kCacheOnReceiver) {}
virtual ~ElementHandlerCompiler() {}
Register PropertyHandlerCompiler::CheckPrototypes(
- Handle<HeapType> type, Register object_reg, Handle<JSObject> holder,
- Register holder_reg, Register scratch1, Register scratch2,
- Handle<Name> name, Label* miss, PrototypeCheckType check) {
- Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
+ Register object_reg, Handle<JSObject> holder, Register holder_reg,
+ Register scratch1, Register scratch2, Handle<Name> name, Label* miss,
+ PrototypeCheckType check) {
+ Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
// Make sure there's no overlap between holder and object registers.
ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
- if (type->IsConstant()) {
- current = Handle<JSObject>::cast(type->AsConstant()->Value());
+ if (type()->IsConstant()) {
+ current = Handle<JSObject>::cast(type()->AsConstant()->Value());
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
}
-Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type,
- Register object_reg,
+Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> callback) {
Label miss;
- Register reg = FrontendHeader(type, object_reg, holder, name, &miss);
+ Register reg = FrontendHeader(object_reg, holder, name, &miss);
if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
ASSERT(!reg.is(scratch2()));
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(
- Register holder_reg, Handle<Object> object,
- Handle<JSObject> interceptor_holder, LookupResult* lookup,
- Handle<Name> name) {
+ Register holder_reg, Handle<JSObject> interceptor_holder,
+ LookupResult* lookup, Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS &&
lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
- ExecutableAccessorInfo* callback =
- ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
- compile_followup_inline = callback->getter() != NULL &&
- callback->IsCompatibleReceiver(*object);
+ Handle<ExecutableAccessorInfo> callback(
+ ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
+ compile_followup_inline =
+ callback->getter() != NULL &&
+ ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback,
+ type());
}
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg =
- Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
+ Register holder_reg = Frontend(receiver(), holder, name);
__ PopReturnAddressTo(scratch1());
__ Push(receiver());
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) {
- NonexistentFrontend(type, last, name);
+ Handle<JSObject> last, Handle<Name> name) {
+ NonexistentFrontend(last, name);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
- Handle<HeapType> type, Handle<GlobalObject> global,
- Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
+ Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name,
+ bool is_dont_delete) {
Label miss;
- // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
- // rax is used as receiver(), which we would otherwise clobber before a
- // potential miss.
- FrontendHeader(type, receiver(), global, name, &miss);
+ FrontendHeader(receiver(), global, name, &miss);
// Get the value from the cell.
- __ Move(rbx, cell);
- __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset));
+ Register result = StoreIC::ValueRegister();
+ __ Move(result, cell);
+ __ movp(result, FieldOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
- __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
+ __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
__ j(equal, &miss);
} else if (FLAG_debug_code) {
- __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
+ __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
- __ movp(rax, rbx);
__ ret(0);
FrontendFooter(name, &miss);