}
-void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss) {
+void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
- __ b(success);
+ Label success;
+ __ b(&success);
__ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
+ __ bind(&success);
}
}
-void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss) {
+void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
- __ b(success);
+ Label success;
+ __ b(&success);
GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind()));
+ __ bind(&success);
}
}
Register LoadStubCompiler::CallbackHandlerFrontend(
- Handle<JSObject> object,
+ Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
- Label* success,
Handle<Object> callback) {
Label miss;
__ b(ne, &miss);
}
- HandlerFrontendFooter(name, success, &miss);
+ HandlerFrontendFooter(name, &miss);
return reg;
}
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
Handle<Name> name) {
}
+void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
+ Label success;
+ // Check that the object is a boolean.
+ __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+ __ cmp(object, ip);
+ __ b(eq, &success);
+ __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+ __ cmp(object, ip);
+ __ b(ne, miss);
+ __ bind(&success);
+}
+
+
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
- CheckType check,
- Label* success) {
+ CheckType check) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
break;
}
case BOOLEAN_CHECK: {
- Label fast;
- // Check that the object is a boolean.
- __ LoadRoot(ip, Heap::kTrueValueRootIndex);
- __ cmp(r1, ip);
- __ b(eq, &fast);
- __ LoadRoot(ip, Heap::kFalseValueRootIndex);
- __ cmp(r1, ip);
- __ b(ne, &miss);
- __ bind(&fast);
+ GenerateBooleanCheck(r1, &miss);
+
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
}
}
- __ b(success);
+ Label success;
+ __ b(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
+
+ __ bind(&success);
}
if (!code.is_null()) return code;
}
- Label success;
-
- CompileHandlerFrontend(object, holder, name, check, &success);
- __ bind(&success);
+ CompileHandlerFrontend(object, holder, name, check);
CompileHandlerBackend(function);
// Return the generated code.
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
Register values[] = { value() };
GenerateFastApiCall(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<JSGlobalObject> global) {
- Label success;
+ NonexistentHandlerFrontend(object, last, name, global);
- NonexistentHandlerFrontend(object, last, name, &success, global);
-
- __ bind(&success);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<GlobalObject> global,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete) {
- Label success, miss;
+ Label miss;
HandlerFrontendHeader(object, receiver(), global, name, &miss);
__ b(eq, &miss);
}
- HandlerFrontendFooter(name, &success, &miss);
- __ bind(&success);
+ HandlerFrontendFooter(name, &miss);
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
}
-void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss) {
+void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
- __ jmp(success);
+ Label success;
+ __ jmp(&success);
__ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
+ __ bind(&success);
}
}
-void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss) {
+void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
- __ jmp(success);
+ Label success;
+ __ jmp(&success);
GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind()));
+ __ bind(&success);
}
}
Register LoadStubCompiler::CallbackHandlerFrontend(
- Handle<JSObject> object,
+ Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
- Label* success,
Handle<Object> callback) {
Label miss;
__ j(not_equal, &miss);
}
- HandlerFrontendFooter(name, success, &miss);
+ HandlerFrontendFooter(name, &miss);
return reg;
}
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
Handle<Name> name) {
}
+void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
+ Label success;
+ // Check that the object is a boolean.
+ __ cmp(object, factory()->true_value());
+ __ j(equal, &success);
+ __ cmp(object, factory()->false_value());
+ __ j(not_equal, miss);
+ __ bind(&success);
+}
+
+
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
- CheckType check,
- Label* success) {
+ CheckType check) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
break;
}
case BOOLEAN_CHECK: {
- Label fast;
- // Check that the object is a boolean.
- __ cmp(edx, factory()->true_value());
- __ j(equal, &fast);
- __ cmp(edx, factory()->false_value());
- __ j(not_equal, &miss);
- __ bind(&fast);
+ GenerateBooleanCheck(edx, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
}
}
- __ jmp(success);
+ Label success;
+ __ jmp(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
+
+ __ bind(&success);
}
if (!code.is_null()) return code;
}
- Label success;
-
- CompileHandlerFrontend(object, holder, name, check, &success);
- __ bind(&success);
+ CompileHandlerFrontend(object, holder, name, check);
CompileHandlerBackend(function);
// Return the generated code.
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
__ pop(scratch1()); // remove the return address
__ push(receiver());
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
Register values[] = { value() };
GenerateFastApiCall(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<JSGlobalObject> global) {
- Label success;
+ NonexistentHandlerFrontend(object, last, name, global);
- NonexistentHandlerFrontend(object, last, name, &success, global);
-
- __ bind(&success);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
__ mov(eax, isolate()->factory()->undefined_value());
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<GlobalObject> global,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete) {
- Label success, miss;
+ Label miss;
HandlerFrontendHeader(object, receiver(), global, name, &miss);
// Get the value from the cell.
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
- HandlerFrontendFooter(name, &success, &miss);
- __ bind(&success);
+ HandlerFrontendFooter(name, &miss);
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
}
-InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object,
- JSObject* holder) {
+InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object) {
if (object->IsJSObject()) return OWN_MAP;
// If the object is a value, we use the prototype map for the cache.
}
-JSObject* IC::GetCodeCacheHolder(Isolate* isolate,
+HeapObject* IC::GetCodeCacheHolder(Isolate* isolate,
Object* object,
InlineCacheHolderFlag holder) {
Object* map_owner =
holder == OWN_MAP ? object : object->GetPrototype(isolate);
- ASSERT(map_owner->IsJSObject());
- return JSObject::cast(map_owner);
+ return HeapObject::cast(map_owner);
}
Handle<String> name) {
if (!handler->is_handler()) return set_target(*handler);
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
- receiver, handler, name, strict_mode());
+ name, receiver, handler, strict_mode());
set_target(*ic);
}
}
-void IC::PatchCache(Handle<HeapObject> receiver,
+void IC::PatchCache(Handle<Object> object,
Handle<String> name,
Handle<Code> code) {
+ // TODO(verwaest): Handle smi here as well.
+ if (!object->IsHeapObject()) return;
+
+ Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
switch (state()) {
case UNINITIALIZED:
case PREMONOMORPHIC:
void LoadIC::UpdateCaches(LookupResult* lookup,
Handle<Object> object,
Handle<String> name) {
- // TODO(verwaest): It would be nice to support loading fields from smis as
- // well. For now just fail to update the cache.
- if (!object->IsHeapObject()) return;
-
- Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
-
- Handle<Code> code;
if (state() == UNINITIALIZED) {
// This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay
set_target(*pre_monomorphic_stub());
TRACE_IC("LoadIC", name);
return;
- } else if (!lookup->IsCacheable()) {
+ }
+
+ Handle<Code> code;
+ if (!lookup->IsCacheable()) {
// Bail out if the result is not cacheable.
code = slow_stub();
- } else if (object->IsString() &&
- name->Equals(isolate()->heap()->length_string())) {
- int length_index = String::kLengthOffset / kPointerSize;
- code = SimpleFieldLoad(length_index);
- } else if (!object->IsJSObject()) {
- // TODO(jkummerow): It would be nice to support non-JSObjects in
- // ComputeLoadHandler, then we wouldn't need to go generic here.
- code = slow_stub();
} else if (!lookup->IsProperty()) {
- code = kind() == Code::LOAD_IC
- ? isolate()->stub_cache()->ComputeLoadNonexistent(
- name, Handle<JSObject>::cast(receiver))
- : slow_stub();
+ if (kind() == Code::LOAD_IC) {
+ code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object);
+ } else {
+ code = slow_stub();
+ }
} else {
- code = ComputeHandler(lookup, Handle<JSObject>::cast(receiver), name);
+ code = ComputeHandler(lookup, object, name);
}
- PatchCache(receiver, name, code);
+ PatchCache(object, name, code);
TRACE_IC("LoadIC", name);
}
Handle<Code> IC::ComputeHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
Handle<Object> value) {
+ InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object);
+ Handle<HeapObject> stub_holder(GetCodeCacheHolder(
+ isolate(), *object, cache_holder));
+
Handle<Code> code = isolate()->stub_cache()->FindHandler(
- name, receiver, kind());
+ name, stub_holder, kind(), cache_holder, strict_mode());
if (!code.is_null()) return code;
- code = CompileHandler(lookup, receiver, name, value);
+ code = CompileHandler(lookup, object, name, value, cache_holder);
ASSERT(code->is_handler());
if (code->type() != Code::NORMAL) {
- HeapObject::UpdateMapCodeCache(receiver, name, code);
+ HeapObject::UpdateMapCodeCache(stub_holder, name, code);
}
return code;
Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> unused) {
+ Handle<Object> unused,
+ InlineCacheHolderFlag cache_holder) {
+ if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
+ int length_index = String::kLengthOffset / kPointerSize;
+ return SimpleFieldLoad(length_index);
+ }
+
Handle<JSObject> holder(lookup->holder());
- LoadStubCompiler compiler(isolate(), kind());
+ LoadStubCompiler compiler(isolate(), cache_holder, kind());
switch (lookup->type()) {
case FIELD: {
PropertyIndex field = lookup->GetFieldIndex();
- if (receiver.is_identical_to(holder)) {
+ if (object.is_identical_to(holder)) {
return SimpleFieldLoad(field.translate(holder),
field.is_inobject(holder),
lookup->representation());
}
return compiler.CompileLoadField(
- receiver, holder, name, field, lookup->representation());
+ object, holder, name, field, lookup->representation());
}
case CONSTANT: {
Handle<Object> constant(lookup->GetConstant(), isolate());
// TODO(2803): Don't compute a stub for cons strings because they cannot
// be embedded into code.
if (constant->IsConsString()) break;
- return compiler.CompileLoadConstant(receiver, holder, name, constant);
+ return compiler.CompileLoadConstant(object, holder, name, constant);
}
case NORMAL:
if (kind() != Code::LOAD_IC) break;
Handle<PropertyCell> cell(
global->GetPropertyCell(lookup), isolate());
Handle<Code> code = compiler.CompileLoadGlobal(
- receiver, global, cell, name, lookup->IsDontDelete());
+ object, global, cell, name, lookup->IsDontDelete());
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
- HeapObject::UpdateMapCodeCache(receiver, name, code);
+ Handle<HeapObject> stub_holder(GetCodeCacheHolder(
+ isolate(), *object, cache_holder));
+ HeapObject::UpdateMapCodeCache(stub_holder, name, code);
return code;
}
// There is only one shared stub for loading normalized
// properties. It does not traverse the prototype chain, so the
- // property must be found in the receiver for the stub to be
+ // property must be found in the object for the stub to be
// applicable.
- if (!holder.is_identical_to(receiver)) break;
+ if (!object.is_identical_to(holder)) break;
return isolate()->builtins()->LoadIC_Normal();
case CALLBACKS: {
// Use simple field loads for some well-known callback properties.
int object_offset;
- Handle<Map> map(receiver->map());
- if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
- PropertyIndex index =
- PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
- return compiler.CompileLoadField(
- receiver, receiver, name, index, Representation::Tagged());
+ if (object->IsJSObject()) {
+ Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+ Handle<Map> map(receiver->map());
+ if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
+ PropertyIndex index =
+ PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
+ return compiler.CompileLoadField(
+ receiver, receiver, name, index, Representation::Tagged());
+ }
}
Handle<Object> callback(lookup->GetCallbackObject(), isolate());
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->getter()) == 0) break;
- if (!info->IsCompatibleReceiver(*receiver)) break;
- return compiler.CompileLoadCallback(receiver, holder, name, info);
+ if (!info->IsCompatibleReceiver(*object)) break;
+ return compiler.CompileLoadCallback(object, holder, name, info);
} else if (callback->IsAccessorPair()) {
Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
isolate());
if (holder->IsGlobalObject()) break;
if (!holder->HasFastProperties()) break;
Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
+ if (!object->IsJSObject() &&
+ !function->IsBuiltin() &&
+ function->shared()->is_classic_mode()) {
+ // Calling non-strict non-builtins with a value as the receiver
+ // requires boxing.
+ break;
+ }
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
- call_optimization.IsCompatibleReceiver(*receiver)) {
+ call_optimization.IsCompatibleReceiver(*object)) {
return compiler.CompileLoadCallback(
- receiver, holder, name, call_optimization);
+ object, holder, name, call_optimization);
}
- return compiler.CompileLoadViaGetter(receiver, holder, name, function);
+ return compiler.CompileLoadViaGetter(object, holder, name, function);
}
// TODO(dcarney): Handle correctly.
if (callback->IsDeclaredAccessorInfo()) break;
}
case INTERCEPTOR:
ASSERT(HasInterceptorGetter(*holder));
- return compiler.CompileLoadInterceptor(receiver, holder, name);
+ return compiler.CompileLoadInterceptor(object, holder, name);
default:
break;
}
Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> value) {
+ Handle<Object> value,
+ InlineCacheHolderFlag cache_holder) {
+ ASSERT(cache_holder == OWN_MAP);
+ // This is currently guaranteed by checks in StoreIC::Store.
+ Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+
Handle<JSObject> holder(lookup->holder());
StoreStubCompiler compiler(isolate(), strict_mode(), kind());
switch (lookup->type()) {
// Determines which map must be used for keeping the code stub.
// These methods should not be called with undefined or null.
- static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
- JSObject* holder);
- static inline JSObject* GetCodeCacheHolder(Isolate* isolate,
- Object* object,
- InlineCacheHolderFlag holder);
+ static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object);
+ // TODO(verwaest): This currently returns a HeapObject rather than JSObject*
+ // since loading the IC for loading the length from strings are stored on
+ // the string map directly, rather than on the JSObject-typed prototype.
+ static inline HeapObject* GetCodeCacheHolder(Isolate* isolate,
+ Object* object,
+ InlineCacheHolderFlag holder);
static bool IsCleared(Code* code) {
InlineCacheState state = code->ic_state();
// Compute the handler either by compiling or by retrieving a cached version.
Handle<Code> ComputeHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> value) {
+ Handle<Object> value,
+ InlineCacheHolderFlag cache_holder) {
UNREACHABLE();
return Handle<Code>::null();
}
void CopyICToMegamorphicCache(Handle<String> name);
bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
- void PatchCache(Handle<HeapObject> receiver,
+ void PatchCache(Handle<Object> object,
Handle<String> name,
Handle<Code> code);
virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
Handle<String> name);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> unused);
+ Handle<Object> unused,
+ InlineCacheHolderFlag cache_holder);
private:
// Stub accessors.
Handle<String> name,
Handle<Object> value);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> value);
+ Handle<Object> value,
+ InlineCacheHolderFlag cache_holder);
private:
void set_target(Code* code) {
Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
ExtraICState extra_ic_state,
+ InlineCacheHolderFlag holder,
StubType type,
- int argc,
- InlineCacheHolderFlag holder) {
+ int argc) {
return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
}
static inline Flags ComputeMonomorphicFlags(
Kind kind,
ExtraICState extra_ic_state = kNoExtraICState,
+ InlineCacheHolderFlag holder = OWN_MAP,
StubType type = NORMAL,
- int argc = -1,
- InlineCacheHolderFlag holder = OWN_MAP);
+ int argc = -1);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
static inline StubType ExtractTypeFromFlags(Flags flags);
Handle<Code> StubCache::FindIC(Handle<Name> name,
Handle<Map> stub_holder_map,
Code::Kind kind,
- Code::ExtraICState extra_state) {
- Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state);
+ Code::ExtraICState extra_state,
+ InlineCacheHolderFlag cache_holder) {
+ Code::Flags flags = Code::ComputeMonomorphicFlags(
+ kind, extra_state, cache_holder);
Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
}
-Handle<Code> StubCache::FindIC(Handle<Name> name,
- Handle<JSObject> stub_holder,
- Code::Kind kind,
- Code::ExtraICState extra_ic_state) {
- return FindIC(name, Handle<Map>(stub_holder->map()), kind, extra_ic_state);
-}
-
-
Handle<Code> StubCache::FindHandler(Handle<Name> name,
- Handle<JSObject> receiver,
+ Handle<HeapObject> stub_holder,
Code::Kind kind,
+ InlineCacheHolderFlag cache_holder,
StrictModeFlag strict_mode) {
Code::ExtraICState extra_ic_state = Code::kNoExtraICState;
if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) {
STANDARD_STORE, strict_mode);
}
Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::HANDLER, extra_ic_state, Code::NORMAL, kind);
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
+ Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind);
+
+ Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
return Handle<Code>::null();
}
-Handle<Code> StubCache::ComputeMonomorphicIC(Handle<HeapObject> receiver,
+Handle<Code> StubCache::ComputeMonomorphicIC(Handle<Name> name,
+ Handle<HeapObject> object,
Handle<Code> handler,
- Handle<Name> name,
StrictModeFlag strict_mode) {
Code::Kind kind = handler->handler_kind();
- Handle<Map> map(receiver->map());
- Handle<Code> ic = FindIC(name, map, kind, strict_mode);
+ // Use the same cache holder for the IC as for the handler.
+ InlineCacheHolderFlag cache_holder =
+ Code::ExtractCacheHolderFromFlags(handler->flags());
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
+ isolate(), *object, cache_holder));
+ Handle<Map> stub_holder_map(stub_holder->map());
+ Handle<Code> ic = FindIC(
+ name, stub_holder_map, kind, strict_mode, cache_holder);
if (!ic.is_null()) return ic;
+ Handle<Map> map(object->map());
if (kind == Code::LOAD_IC) {
- LoadStubCompiler ic_compiler(isolate());
+ LoadStubCompiler ic_compiler(isolate(), cache_holder);
ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
} else if (kind == Code::KEYED_LOAD_IC) {
- KeyedLoadStubCompiler ic_compiler(isolate());
+ KeyedLoadStubCompiler ic_compiler(isolate(), cache_holder);
ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
} else if (kind == Code::STORE_IC) {
StoreStubCompiler ic_compiler(isolate(), strict_mode);
ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
}
- HeapObject::UpdateMapCodeCache(receiver, name, ic);
+ HeapObject::UpdateMapCodeCache(stub_holder, name, ic);
return ic;
}
Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
- Handle<JSObject> receiver) {
+ Handle<Object> object) {
+ InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
+ isolate(), *object, cache_holder));
// If no global objects are present in the prototype chain, the load
// nonexistent IC stub can be shared for all names for a given map
// and we use the empty string for the map cache in that case. If
// specific to the name.
Handle<Name> cache_name = factory()->empty_string();
Handle<JSObject> current;
- Handle<Object> next = receiver;
+ Handle<Object> next = stub_holder;
Handle<JSGlobalObject> global;
do {
current = Handle<JSObject>::cast(next);
// Compile the stub that is either shared for all names or
// name specific if there are global objects involved.
- Handle<Code> handler = FindHandler(cache_name, receiver, Code::LOAD_IC);
+ Handle<Code> handler = FindHandler(
+ cache_name, stub_holder, Code::LOAD_IC, cache_holder);
if (!handler.is_null()) return handler;
- LoadStubCompiler compiler(isolate_);
+ LoadStubCompiler compiler(isolate_, cache_holder);
handler =
- compiler.CompileLoadNonexistent(receiver, current, cache_name, global);
- HeapObject::UpdateMapCodeCache(receiver, cache_name, handler);
+ compiler.CompileLoadNonexistent(object, current, cache_name, global);
+ HeapObject::UpdateMapCodeCache(stub_holder, cache_name, handler);
return handler;
}
Handle<JSObject> holder,
Handle<JSFunction> function) {
// Compute the check type and the map.
- InlineCacheHolderFlag cache_holder =
- IC::GetCodeCacheForObject(*object, *holder);
- Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
+ InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
isolate_, *object, cache_holder));
// Compute check type based on receiver/holder.
}
Code::Flags flags = Code::ComputeMonomorphicFlags(
- kind, extra_state, Code::CONSTANT, argc, cache_holder);
+ kind, extra_state, cache_holder, Code::CONSTANT, argc);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
Handle<JSObject> holder,
PropertyIndex index) {
// Compute the check type and the map.
- InlineCacheHolderFlag cache_holder =
- IC::GetCodeCacheForObject(*object, *holder);
- Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
+ InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
isolate_, *object, cache_holder));
// TODO(1233596): We cannot do receiver map check for non-JS objects
}
Code::Flags flags = Code::ComputeMonomorphicFlags(
- kind, extra_state, Code::FIELD, argc, cache_holder);
+ kind, extra_state, cache_holder, Code::FIELD, argc);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
Handle<Object> object,
Handle<JSObject> holder) {
// Compute the check type and the map.
- InlineCacheHolderFlag cache_holder =
- IC::GetCodeCacheForObject(*object, *holder);
- Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
+ InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
isolate_, *object, cache_holder));
// TODO(1233596): We cannot do receiver map check for non-JS objects
}
Code::Flags flags = Code::ComputeMonomorphicFlags(
- kind, extra_state, Code::INTERCEPTOR, argc, cache_holder);
+ kind, extra_state, cache_holder, Code::INTERCEPTOR, argc);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
Handle<PropertyCell> cell,
Handle<JSFunction> function) {
Code::Flags flags = Code::ComputeMonomorphicFlags(
- kind, extra_state, Code::NORMAL, argc);
+ kind, extra_state, OWN_MAP, Code::NORMAL, argc);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
masm_.GetCode(&desc);
Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
#ifdef ENABLE_DISASSEMBLER
- if (FLAG_print_code_stubs) {
- CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
- code->Disassemble(name, trace_scope.file());
- }
+ if (FLAG_print_code_stubs) code->Disassemble(name);
#endif
return code;
}
Register LoadStubCompiler::HandlerFrontendHeader(
- Handle<JSObject> object,
+ Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
- return CheckPrototypes(object, object_reg, holder,
+ Handle<JSObject> receiver;
+ PrototypeCheckType check_type = CHECK_ALL_MAPS;
+ int function_index = -1;
+ if (object->IsJSObject()) {
+ receiver = Handle<JSObject>::cast(object);
+ check_type = SKIP_RECEIVER;
+ } else {
+ if (object->IsString()) {
+ function_index = Context::STRING_FUNCTION_INDEX;
+ } else if (object->IsSymbol()) {
+ function_index = Context::SYMBOL_FUNCTION_INDEX;
+ } else if (object->IsNumber()) {
+ function_index = Context::NUMBER_FUNCTION_INDEX;
+ } else {
+ ASSERT(object->IsBoolean());
+ // Booleans use the generic oddball map, so an additional check is
+ // needed to ensure the receiver is really a boolean.
+ GenerateBooleanCheck(object_reg, miss);
+ function_index = Context::BOOLEAN_FUNCTION_INDEX;
+ }
+
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), function_index, scratch1(), miss);
+ receiver = handle(JSObject::cast(object->GetPrototype(isolate())));
+ object_reg = scratch1();
+ }
+
+ // Check that the maps starting from the prototype haven't changed.
+ return CheckPrototypes(receiver, object_reg, holder,
scratch1(), scratch2(), scratch3(),
- name, miss, SKIP_RECEIVER);
+ name, miss, check_type);
}
// HandlerFrontend for store uses the name register. It has to be restored
// before a miss.
Register StoreStubCompiler::HandlerFrontendHeader(
- Handle<JSObject> object,
+ Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
- return CheckPrototypes(object, object_reg, holder,
+ return CheckPrototypes(Handle<JSObject>::cast(object), object_reg, holder,
this->name(), scratch1(), scratch2(),
name, miss, SKIP_RECEIVER);
}
-Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<JSObject> object,
+Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<Name> name,
- Label* success) {
+ Handle<Name> name) {
Label miss;
Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
- HandlerFrontendFooter(name, success, &miss);
+ HandlerFrontendFooter(name, &miss);
+
return reg;
}
void LoadStubCompiler::NonexistentHandlerFrontend(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
- Label* success,
Handle<JSGlobalObject> global) {
Label miss;
- Register holder =
- HandlerFrontendHeader(object, receiver(), last, name, &miss);
+ Register holder = HandlerFrontendHeader(
+ object, receiver(), last, name, &miss);
if (!last->HasFastProperties() &&
!last->IsJSGlobalObject() &&
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
}
- HandlerFrontendFooter(name, success, &miss);
+ HandlerFrontendFooter(name, &miss);
}
Handle<Code> LoadStubCompiler::CompileLoadField(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
PropertyIndex field,
Handle<Code> LoadStubCompiler::CompileLoadConstant(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> value) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
GenerateLoadConstant(value);
// Return the generated code.
Handle<Code> LoadStubCompiler::CompileLoadCallback(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Label success;
-
Register reg = CallbackHandlerFrontend(
- object, receiver(), holder, name, &success, callback);
- __ bind(&success);
+ object, receiver(), holder, name, callback);
GenerateLoadCallback(reg, callback);
// Return the generated code.
Handle<Code> LoadStubCompiler::CompileLoadCallback(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call());
- Label success;
-
Handle<JSFunction> callback = call_optimization.constant_function();
- CallbackHandlerFrontend(
- object, receiver(), holder, name, &success, callback);
- __ bind(&success);
+ CallbackHandlerFrontend(object, receiver(), holder, name, callback);
GenerateLoadCallback(call_optimization);
// Return the generated code.
Handle<Code> LoadStubCompiler::CompileLoadInterceptor(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name) {
- Label success;
-
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
- Register reg = HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ Register reg = HandlerFrontend(object, receiver(), holder, name);
// TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer.
GenerateLoadInterceptor(reg, object, holder, &lookup, name);
Handle<JSObject> interceptor_holder,
Handle<Name> name,
LookupResult* lookup) {
- Label success;
Handle<JSObject> holder(lookup->holder());
if (lookup->IsField()) {
PropertyIndex field = lookup->GetFieldIndex();
// We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder.
Register reg = HandlerFrontend(
- interceptor_holder, interceptor_reg, holder, name, &success);
- __ bind(&success);
+ interceptor_holder, interceptor_reg, holder, name);
GenerateLoadField(
reg, holder, field, lookup->representation());
}
ASSERT(callback->getter() != NULL);
Register reg = CallbackHandlerFrontend(
- interceptor_holder, interceptor_reg, holder, name, &success, callback);
- __ bind(&success);
+ interceptor_holder, interceptor_reg, holder, name, callback);
GenerateLoadCallback(reg, callback);
}
}
Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<JSFunction> getter) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
-
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
GenerateLoadViaGetter(masm(), receiver(), getter);
// Return the generated code.
Handle<JSObject> holder,
Handle<Name> name,
Handle<JSFunction> setter) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
-
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
GenerateStoreViaSetter(masm(), setter);
return GetCode(kind(), Code::CALLBACKS, name);
Code::StubType type,
Handle<Name> name) {
Code::Flags flags = Code::ComputeFlags(
- Code::HANDLER, MONOMORPHIC, extra_state(), type, kind);
+ Code::HANDLER, MONOMORPHIC, extra_state(), type, kind, cache_holder_);
Handle<Code> code = GetCodeWithFlags(flags, name);
PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
JitEvent(name, code);
Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
Handle<Name> name) {
int argc = arguments_.immediate();
- Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
- extra_state_,
- type,
- argc,
- cache_holder_);
+ Code::Flags flags = Code::ComputeMonomorphicFlags(
+ kind_, extra_state_, cache_holder_, type, argc);
return GetCodeWithFlags(flags, name);
}
Handle<Code> FindIC(Handle<Name> name,
Handle<Map> stub_holder_map,
Code::Kind kind,
- Code::ExtraICState extra_state = Code::kNoExtraICState);
-
- Handle<Code> FindIC(Handle<Name> name,
- Handle<JSObject> stub_holder,
- Code::Kind kind,
- Code::ExtraICState extra_state = Code::kNoExtraICState);
+ Code::ExtraICState extra_state = Code::kNoExtraICState,
+ InlineCacheHolderFlag cache_holder = OWN_MAP);
Handle<Code> FindHandler(Handle<Name> name,
- Handle<JSObject> receiver,
+ Handle<HeapObject> stub_holder,
Code::Kind kind,
+ InlineCacheHolderFlag cache_holder = OWN_MAP,
StrictModeFlag strict_mode = kNonStrictMode);
- Handle<Code> ComputeMonomorphicIC(Handle<HeapObject> receiver,
+ Handle<Code> ComputeMonomorphicIC(Handle<Name> name,
+ Handle<HeapObject> receiver,
Handle<Code> handler,
- Handle<Name> name,
StrictModeFlag strict_mode);
- // Computes the right stub matching. Inserts the result in the
- // cache before returning. This might compile a stub if needed.
- Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
- Handle<JSObject> object);
-
- // ---
+ Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<Object> object);
Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
Label* miss,
PrototypeCheckType check = CHECK_ALL_MAPS);
+ void GenerateBooleanCheck(Register object, Label* miss);
protected:
Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
class BaseLoadStoreStubCompiler: public StubCompiler {
public:
- BaseLoadStoreStubCompiler(Isolate* isolate, Code::Kind kind)
- : StubCompiler(isolate), kind_(kind) {
+ BaseLoadStoreStubCompiler(Isolate* isolate,
+ Code::Kind kind,
+ InlineCacheHolderFlag cache_holder = OWN_MAP)
+ : StubCompiler(isolate), kind_(kind), cache_holder_(cache_holder) {
InitializeRegisters();
}
virtual ~BaseLoadStoreStubCompiler() { }
}
protected:
- virtual Register HandlerFrontendHeader(Handle<JSObject> object,
+ virtual Register HandlerFrontendHeader(Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) = 0;
- virtual void HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss) = 0;
+ virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss) = 0;
- Register HandlerFrontend(Handle<JSObject> object,
+ Register HandlerFrontend(Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<Name> name,
- Label* success);
+ Handle<Name> name);
Handle<Code> GetCode(Code::Kind kind,
Code::StubType type,
void InitializeRegisters();
Code::Kind kind_;
+ InlineCacheHolderFlag cache_holder_;
Register* registers_;
};
class LoadStubCompiler: public BaseLoadStoreStubCompiler {
public:
- LoadStubCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC)
- : BaseLoadStoreStubCompiler(isolate, kind) { }
+ LoadStubCompiler(Isolate* isolate,
+ InlineCacheHolderFlag cache_holder = OWN_MAP,
+ Code::Kind kind = Code::LOAD_IC)
+ : BaseLoadStoreStubCompiler(isolate, kind, cache_holder) { }
virtual ~LoadStubCompiler() { }
- Handle<Code> CompileLoadField(Handle<JSObject> object,
+ Handle<Code> CompileLoadField(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
PropertyIndex index,
Representation representation);
- Handle<Code> CompileLoadCallback(Handle<JSObject> object,
+ Handle<Code> CompileLoadCallback(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
- Handle<Code> CompileLoadCallback(Handle<JSObject> object,
+ Handle<Code> CompileLoadCallback(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization);
- Handle<Code> CompileLoadConstant(Handle<JSObject> object,
+ Handle<Code> CompileLoadConstant(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<Object> value);
- Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
+ Handle<Code> CompileLoadInterceptor(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name);
- Handle<Code> CompileLoadViaGetter(Handle<JSObject> object,
+ Handle<Code> CompileLoadViaGetter(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
Handle<JSFunction> getter);
Register receiver,
Handle<JSFunction> getter);
- Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
+ Handle<Code> CompileLoadNonexistent(Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<JSGlobalObject> global);
- Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
+ Handle<Code> CompileLoadGlobal(Handle<Object> object,
Handle<GlobalObject> holder,
Handle<PropertyCell> cell,
Handle<Name> name,
static Register* registers();
protected:
- virtual Register HandlerFrontendHeader(Handle<JSObject> object,
+ virtual Register HandlerFrontendHeader(Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss);
- virtual void HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss);
+ virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
- Register CallbackHandlerFrontend(Handle<JSObject> object,
+ Register CallbackHandlerFrontend(Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
- Label* success,
Handle<Object> callback);
- void NonexistentHandlerFrontend(Handle<JSObject> object,
+ void NonexistentHandlerFrontend(Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
- Label* success,
Handle<JSGlobalObject> global);
void GenerateLoadField(Register reg,
Handle<ExecutableAccessorInfo> callback);
void GenerateLoadCallback(const CallOptimization& call_optimization);
void GenerateLoadInterceptor(Register holder_reg,
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> holder,
LookupResult* lookup,
Handle<Name> name);
class KeyedLoadStubCompiler: public LoadStubCompiler {
public:
- explicit KeyedLoadStubCompiler(Isolate* isolate)
- : LoadStubCompiler(isolate, Code::KEYED_LOAD_IC) { }
+ KeyedLoadStubCompiler(Isolate* isolate,
+ InlineCacheHolderFlag cache_holder = OWN_MAP)
+ : LoadStubCompiler(isolate, cache_holder, Code::KEYED_LOAD_IC) { }
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
}
protected:
- virtual Register HandlerFrontendHeader(Handle<JSObject> object,
+ virtual Register HandlerFrontendHeader(Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss);
- virtual void HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss);
+ virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
void GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name);
void CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
- CheckType check,
- Label* success);
+ CheckType check);
void CompileHandlerBackend(Handle<JSFunction> function);
Code::ExtraICState extra_ic_state =
CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION);
- Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
- extra_ic_state,
- Code::NORMAL,
- arity,
- OWN_MAP);
+ Code::Flags flags = Code::ComputeMonomorphicFlags(
+ Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity);
CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types);
}
}
-void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss) {
+void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
- __ jmp(success);
+ Label success;
+ __ jmp(&success);
__ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
+ __ bind(&success);
}
}
-void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
- Label* success,
- Label* miss) {
+void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
- __ jmp(success);
+ Label success;
+ __ jmp(&success);
GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind()));
+ __ bind(&success);
}
}
Register LoadStubCompiler::CallbackHandlerFrontend(
- Handle<JSObject> object,
+ Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
- Label* success,
Handle<Object> callback) {
Label miss;
__ j(not_equal, &miss);
}
- HandlerFrontendFooter(name, success, &miss);
+ HandlerFrontendFooter(name, &miss);
return reg;
}
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
Handle<Name> name) {
}
+void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
+ Label success;
+ // Check that the object is a boolean.
+ __ CompareRoot(object, Heap::kTrueValueRootIndex);
+ __ j(equal, &success);
+ __ CompareRoot(object, Heap::kFalseValueRootIndex);
+ __ j(not_equal, miss);
+ __ bind(&success);
+}
+
+
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
- CheckType check,
- Label* success) {
+ CheckType check) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
break;
}
case BOOLEAN_CHECK: {
- Label fast;
- // Check that the object is a boolean.
- __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
- __ j(equal, &fast);
- __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
- __ j(not_equal, &miss);
- __ bind(&fast);
+ GenerateBooleanCheck(rdx, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
}
}
- __ jmp(success);
+ Label success;
+ __ jmp(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
+
+ __ bind(&success);
}
if (!code.is_null()) return code;
}
- Label success;
-
- CompileHandlerFrontend(object, holder, name, check, &success);
- __ bind(&success);
+ CompileHandlerFrontend(object, holder, name, check);
CompileHandlerBackend(function);
// Return the generated code.
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
__ PopReturnAddressTo(scratch1());
__ push(receiver());
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
- Label success;
- HandlerFrontend(object, receiver(), holder, name, &success);
- __ bind(&success);
+ HandlerFrontend(object, receiver(), holder, name);
Register values[] = { value() };
GenerateFastApiCall(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<JSGlobalObject> global) {
- Label success;
+ NonexistentHandlerFrontend(object, last, name, global);
- NonexistentHandlerFrontend(object, last, name, &success, global);
-
- __ bind(&success);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
- Handle<JSObject> object,
+ Handle<Object> object,
Handle<GlobalObject> global,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete) {
- Label success, miss;
+ 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.
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
- HandlerFrontendFooter(name, &success, &miss);
- __ bind(&success);
+ HandlerFrontendFooter(name, &miss);
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Object.defineProperty(Boolean.prototype, "v",
+ {get:function() { return this; }});
+
+function f(b) {
+ return b.v;
+}
+
+assertEquals("object", typeof f(true));
+assertEquals("object", typeof f(true));
+assertEquals("object", typeof f(true));
+assertEquals("object", typeof f(true));