| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index 640b188ab23bb1b62b59b5f9458ea6b811660f4e..187023eddb9f7c920c1934d181f059ec145ca529 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -1005,7 +1005,7 @@ void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
|
| 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);
|
| }
|
|
|
| @@ -1035,9 +1035,13 @@ bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
|
| }
|
|
|
|
|
| -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:
|
| @@ -1097,13 +1101,6 @@ Handle<Code> LoadIC::SimpleFieldLoad(int offset,
|
| 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
|
| @@ -1111,27 +1108,23 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
| 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);
|
| }
|
|
|
| @@ -1144,18 +1137,22 @@ void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
|
|
|
|
|
| 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;
|
| @@ -1163,29 +1160,35 @@ Handle<Code> IC::ComputeHandler(LookupResult* lookup,
|
|
|
|
|
| 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;
|
| @@ -1194,26 +1197,31 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
|
| 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());
|
| @@ -1221,8 +1229,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
|
| 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());
|
| @@ -1230,13 +1238,20 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
|
| 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;
|
| @@ -1246,7 +1261,7 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
|
| }
|
| case INTERCEPTOR:
|
| ASSERT(HasInterceptorGetter(*holder));
|
| - return compiler.CompileLoadInterceptor(receiver, holder, name);
|
| + return compiler.CompileLoadInterceptor(object, holder, name);
|
| default:
|
| break;
|
| }
|
| @@ -1582,9 +1597,14 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
|
|
|
|
| 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()) {
|
|
|