| Index: src/stub-cache.cc
|
| diff --git a/src/stub-cache.cc b/src/stub-cache.cc
|
| index 7cb02f6a241f97bbe24bdd4b3c4d61798a32244c..f23e5aaeb355d167790e6a22369d5b2b80db23ff 100644
|
| --- a/src/stub-cache.cc
|
| +++ b/src/stub-cache.cc
|
| @@ -116,9 +116,9 @@ Handle<Code> StubCache::FindIC(Handle<Name> name,
|
| Handle<Code> StubCache::FindHandler(Handle<Name> name,
|
| Handle<Map> stub_holder,
|
| Code::Kind kind,
|
| - InlineCacheHolderFlag cache_holder) {
|
| - Code::Flags flags = Code::ComputeMonomorphicFlags(
|
| - Code::HANDLER, kNoExtraICState, cache_holder, Code::NORMAL, kind);
|
| + InlineCacheHolderFlag cache_holder,
|
| + Code::StubType type) {
|
| + Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder);
|
|
|
| Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_);
|
| if (probe->IsCode()) return Handle<Code>::cast(probe);
|
| @@ -127,11 +127,11 @@ Handle<Code> StubCache::FindHandler(Handle<Name> name,
|
|
|
|
|
| Handle<Code> StubCache::ComputeMonomorphicIC(
|
| + Code::Kind kind,
|
| Handle<Name> name,
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<Code> handler,
|
| ExtraICState extra_ic_state) {
|
| - Code::Kind kind = handler->handler_kind();
|
| InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type);
|
|
|
| Handle<Map> stub_holder;
|
| @@ -139,7 +139,7 @@ Handle<Code> StubCache::ComputeMonomorphicIC(
|
| // There are multiple string maps that all use the same prototype. That
|
| // prototype cannot hold multiple handlers, one for each of the string maps,
|
| // for a single name. Hence, turn off caching of the IC.
|
| - bool can_be_cached = !type->Is(Type::String());
|
| + bool can_be_cached = !type->Is(HeapType::String());
|
| if (can_be_cached) {
|
| stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
|
| ic = FindIC(name, stub_holder, kind, extra_ic_state, flag);
|
| @@ -169,7 +169,7 @@ Handle<Code> StubCache::ComputeMonomorphicIC(
|
|
|
|
|
| Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
|
| - Handle<Type> type) {
|
| + Handle<HeapType> type) {
|
| InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type);
|
| Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
|
| // If no dictionary mode objects are present in the prototype chain, the load
|
| @@ -192,10 +192,12 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
|
| // 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, stub_holder, Code::LOAD_IC, flag);
|
| - if (!handler.is_null()) return handler;
|
| + cache_name, stub_holder, Code::LOAD_IC, flag, Code::FAST);
|
| + if (!handler.is_null()) {
|
| + return handler;
|
| + }
|
|
|
| - LoadStubCompiler compiler(isolate_, flag);
|
| + LoadStubCompiler compiler(isolate_, kNoExtraICState, flag);
|
| handler = compiler.CompileLoadNonexistent(type, last, cache_name);
|
| Map::UpdateCodeCache(stub_holder, cache_name, handler);
|
| return handler;
|
| @@ -247,163 +249,7 @@ Handle<Code> StubCache::ComputeKeyedStoreElement(
|
| }
|
|
|
|
|
| -#define CALL_LOGGER_TAG(kind, type) \
|
| - (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
|
| -
|
| -Handle<Code> StubCache::ComputeCallConstant(int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state,
|
| - Handle<Name> name,
|
| - Handle<Object> object,
|
| - Handle<JSObject> holder,
|
| - Handle<JSFunction> function) {
|
| - // Compute the check type and the map.
|
| - InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
|
| - Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
|
| - isolate_, *object, cache_holder));
|
| -
|
| - // Compute check type based on receiver/holder.
|
| - CheckType check = RECEIVER_MAP_CHECK;
|
| - if (object->IsString()) {
|
| - check = STRING_CHECK;
|
| - } else if (object->IsSymbol()) {
|
| - check = SYMBOL_CHECK;
|
| - } else if (object->IsNumber()) {
|
| - check = NUMBER_CHECK;
|
| - } else if (object->IsBoolean()) {
|
| - check = BOOLEAN_CHECK;
|
| - }
|
| -
|
| - if (check != RECEIVER_MAP_CHECK &&
|
| - !function->IsBuiltin() &&
|
| - function->shared()->is_classic_mode()) {
|
| - // Calling non-strict non-builtins with a value as the receiver
|
| - // requires boxing.
|
| - return Handle<Code>::null();
|
| - }
|
| -
|
| - Code::Flags flags = Code::ComputeMonomorphicFlags(
|
| - kind, extra_state, cache_holder, Code::FAST, argc);
|
| - Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
|
| - isolate_);
|
| - if (probe->IsCode()) return Handle<Code>::cast(probe);
|
| -
|
| - CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
|
| - Handle<Code> code =
|
| - compiler.CompileCallConstant(object, holder, name, check, function);
|
| - code->set_check_type(check);
|
| - ASSERT(flags == code->flags());
|
| - PROFILE(isolate_,
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
|
| -
|
| - HeapObject::UpdateMapCodeCache(stub_holder, name, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallField(int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state,
|
| - Handle<Name> name,
|
| - Handle<Object> object,
|
| - Handle<JSObject> holder,
|
| - PropertyIndex index) {
|
| - // Compute the check type and the map.
|
| - 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
|
| - // because they may be represented as immediates without a
|
| - // map. Instead, we check against the map in the holder.
|
| - if (object->IsNumber() || object->IsSymbol() ||
|
| - object->IsBoolean() || object->IsString()) {
|
| - object = holder;
|
| - }
|
| -
|
| - Code::Flags flags = Code::ComputeMonomorphicFlags(
|
| - kind, extra_state, cache_holder, Code::FAST, argc);
|
| - Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
|
| - isolate_);
|
| - if (probe->IsCode()) return Handle<Code>::cast(probe);
|
| -
|
| - CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
|
| - Handle<Code> code =
|
| - compiler.CompileCallField(Handle<JSObject>::cast(object),
|
| - holder, index, name);
|
| - ASSERT(flags == code->flags());
|
| - PROFILE(isolate_,
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
|
| - HeapObject::UpdateMapCodeCache(stub_holder, name, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallInterceptor(int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state,
|
| - Handle<Name> name,
|
| - Handle<Object> object,
|
| - Handle<JSObject> holder) {
|
| - // Compute the check type and the map.
|
| - 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
|
| - // because they may be represented as immediates without a
|
| - // map. Instead, we check against the map in the holder.
|
| - if (object->IsNumber() || object->IsSymbol() ||
|
| - object->IsBoolean() || object->IsString()) {
|
| - object = holder;
|
| - }
|
| -
|
| - Code::Flags flags = Code::ComputeMonomorphicFlags(
|
| - kind, extra_state, cache_holder, Code::FAST, argc);
|
| - Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
|
| - isolate_);
|
| - if (probe->IsCode()) return Handle<Code>::cast(probe);
|
| -
|
| - CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
|
| - Handle<Code> code =
|
| - compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
|
| - holder, name);
|
| - ASSERT(flags == code->flags());
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
|
| - HeapObject::UpdateMapCodeCache(stub_holder, name, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallGlobal(int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state,
|
| - Handle<Name> name,
|
| - Handle<JSObject> receiver,
|
| - Handle<GlobalObject> holder,
|
| - Handle<PropertyCell> cell,
|
| - Handle<JSFunction> function) {
|
| - Code::Flags flags = Code::ComputeMonomorphicFlags(
|
| - 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);
|
| -
|
| - CallStubCompiler compiler(isolate(), argc, kind, extra_state);
|
| - Handle<Code> code =
|
| - compiler.CompileCallGlobal(receiver, holder, cell, function, name);
|
| - ASSERT(flags == code->flags());
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
|
| - HeapObject::UpdateMapCodeCache(receiver, name, code);
|
| - return code;
|
| -}
|
| -
|
| +#define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type)
|
|
|
| static void FillCache(Isolate* isolate, Handle<Code> code) {
|
| Handle<UnseededNumberDictionary> dictionary =
|
| @@ -414,20 +260,6 @@ static void FillCache(Isolate* isolate, Handle<Code> code) {
|
| }
|
|
|
|
|
| -Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) {
|
| - Code::Flags flags = Code::ComputeFlags(
|
| - kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc);
|
| - UnseededNumberDictionary* dictionary =
|
| - isolate()->heap()->non_monomorphic_cache();
|
| - int entry = dictionary->FindEntry(isolate(), flags);
|
| - ASSERT(entry != -1);
|
| - Object* code = dictionary->ValueAt(entry);
|
| - // This might be called during the marking phase of the collector
|
| - // hence the unchecked cast.
|
| - return reinterpret_cast<Code*>(code);
|
| -}
|
| -
|
| -
|
| Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) {
|
| Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state);
|
| UnseededNumberDictionary* dictionary =
|
| @@ -441,101 +273,6 @@ Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) {
|
| }
|
|
|
|
|
| -Handle<Code> StubCache::ComputeCallInitialize(int argc, Code::Kind kind) {
|
| - Code::Flags flags = Code::ComputeFlags(
|
| - kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallInitialize(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallInitialize(int argc) {
|
| - return ComputeCallInitialize(argc, Code::CALL_IC);
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
|
| - return ComputeCallInitialize(argc, Code::KEYED_CALL_IC);
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallPreMonomorphic(
|
| - int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state) {
|
| - Code::Flags flags =
|
| - Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallNormal(int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state) {
|
| - Code::Flags flags =
|
| - Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallNormal(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallArguments(int argc) {
|
| - Code::Flags flags =
|
| - Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC,
|
| - kNoExtraICState, Code::NORMAL, argc);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallArguments(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallMegamorphic(
|
| - int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state) {
|
| - Code::Flags flags =
|
| - Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
|
| - Code::NORMAL, argc);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallMegamorphic(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state,
|
| ExtraICState extra_state) {
|
| Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state);
|
| @@ -587,26 +324,6 @@ Handle<Code> StubCache::ComputeStore(InlineCacheState ic_state,
|
| }
|
|
|
|
|
| -Handle<Code> StubCache::ComputeCallMiss(int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state) {
|
| - // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
|
| - // and monomorphic stubs are not mixed up together in the stub cache.
|
| - Code::Flags flags =
|
| - Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
|
| - Code::NORMAL, argc, OWN_MAP);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallMiss(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map,
|
| CompareNilICStub& stub) {
|
| Handle<String> name(isolate_->heap()->empty_string());
|
| @@ -638,7 +355,7 @@ Handle<Code> StubCache::ComputeLoadElementPolymorphic(
|
|
|
| TypeHandleList types(receiver_maps->length());
|
| for (int i = 0; i < receiver_maps->length(); i++) {
|
| - types.Add(Type::Class(receiver_maps->at(i), isolate()));
|
| + types.Add(HeapType::Class(receiver_maps->at(i), isolate()));
|
| }
|
| CodeHandleList handlers(receiver_maps->length());
|
| KeyedLoadStubCompiler compiler(isolate_);
|
| @@ -654,14 +371,13 @@ Handle<Code> StubCache::ComputeLoadElementPolymorphic(
|
|
|
|
|
| Handle<Code> StubCache::ComputePolymorphicIC(
|
| + Code::Kind kind,
|
| TypeHandleList* types,
|
| CodeHandleList* handlers,
|
| int number_of_valid_types,
|
| Handle<Name> name,
|
| ExtraICState extra_ic_state) {
|
| -
|
| Handle<Code> handler = handlers->at(0);
|
| - Code::Kind kind = handler->handler_kind();
|
| Code::StubType type = number_of_valid_types == 1 ? handler->type()
|
| : Code::NORMAL;
|
| if (kind == Code::LOAD_IC) {
|
| @@ -701,46 +417,6 @@ Handle<Code> StubCache::ComputeStoreElementPolymorphic(
|
| }
|
|
|
|
|
| -#ifdef ENABLE_DEBUGGER_SUPPORT
|
| -Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
|
| - Code::Kind kind) {
|
| - // Extra IC state is irrelevant for debug break ICs. They jump to
|
| - // the actual call ic to carry out the work.
|
| - Code::Flags flags =
|
| - Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK,
|
| - Code::NORMAL, argc);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallDebugBreak(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
|
| - Code::Kind kind) {
|
| - // Extra IC state is irrelevant for debug break ICs. They jump to
|
| - // the actual call ic to carry out the work.
|
| - Code::Flags flags =
|
| - Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_PREPARE_STEP_IN,
|
| - Code::NORMAL, argc);
|
| - Handle<UnseededNumberDictionary> cache =
|
| - isolate_->factory()->non_monomorphic_cache();
|
| - int entry = cache->FindEntry(isolate_, flags);
|
| - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
| -
|
| - StubCompiler compiler(isolate_);
|
| - Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
|
| - FillCache(isolate_, code);
|
| - return code;
|
| -}
|
| -#endif
|
| -
|
| -
|
| void StubCache::Clear() {
|
| Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
|
| for (int i = 0; i < kPrimaryTableSize; i++) {
|
| @@ -994,83 +670,6 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
|
| }
|
|
|
|
|
| -Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
|
| - int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
| - Code::Kind kind = Code::ExtractKindFromFlags(flags);
|
| - ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
| - if (kind == Code::CALL_IC) {
|
| - CallIC::GenerateInitialize(masm(), argc, extra_state);
|
| - } else {
|
| - KeyedCallIC::GenerateInitialize(masm(), argc);
|
| - }
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
|
| - isolate()->counters()->call_initialize_stubs()->Increment();
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
|
| - *code, code->arguments_count()));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
|
| - int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
| - // The code of the PreMonomorphic stub is the same as the code
|
| - // of the Initialized stub. They just differ on the code object flags.
|
| - Code::Kind kind = Code::ExtractKindFromFlags(flags);
|
| - ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
| - if (kind == Code::CALL_IC) {
|
| - CallIC::GenerateInitialize(masm(), argc, extra_state);
|
| - } else {
|
| - KeyedCallIC::GenerateInitialize(masm(), argc);
|
| - }
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
|
| - isolate()->counters()->call_premonomorphic_stubs()->Increment();
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
|
| - *code, code->arguments_count()));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
|
| - int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
| - Code::Kind kind = Code::ExtractKindFromFlags(flags);
|
| - if (kind == Code::CALL_IC) {
|
| - CallIC::GenerateNormal(masm(), argc);
|
| - } else {
|
| - KeyedCallIC::GenerateNormal(masm(), argc);
|
| - }
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
|
| - isolate()->counters()->call_normal_stubs()->Increment();
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
|
| - *code, code->arguments_count()));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
|
| - int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
| - Code::Kind kind = Code::ExtractKindFromFlags(flags);
|
| - ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
| - if (kind == Code::CALL_IC) {
|
| - CallIC::GenerateMegamorphic(masm(), argc, extra_state);
|
| - } else {
|
| - KeyedCallIC::GenerateMegamorphic(masm(), argc);
|
| - }
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
|
| - isolate()->counters()->call_megamorphic_stubs()->Increment();
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
|
| - *code, code->arguments_count()));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
|
| - return code;
|
| -}
|
| -
|
| -
|
| Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) {
|
| LoadIC::GenerateInitialize(masm());
|
| Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize");
|
| @@ -1092,9 +691,7 @@ Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) {
|
|
|
|
|
| Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) {
|
| - ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
| - ContextualMode mode = LoadIC::GetContextualMode(extra_state);
|
| - LoadIC::GenerateMegamorphic(masm(), mode);
|
| + LoadIC::GenerateMegamorphic(masm());
|
| Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic");
|
| PROFILE(isolate(),
|
| CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0));
|
| @@ -1136,8 +733,7 @@ Handle<Code> StubCompiler::CompileStoreGeneric(Code::Flags flags) {
|
|
|
|
|
| Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) {
|
| - ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
| - StoreIC::GenerateMegamorphic(masm(), extra_state);
|
| + StoreIC::GenerateMegamorphic(masm());
|
| Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic");
|
| PROFILE(isolate(),
|
| CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0));
|
| @@ -1146,71 +742,6 @@ Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) {
|
| }
|
|
|
|
|
| -Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
|
| - int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
| - KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
|
| - CALL_MEGAMORPHIC_TAG),
|
| - *code, code->arguments_count()));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
|
| - int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
| - Code::Kind kind = Code::ExtractKindFromFlags(flags);
|
| - ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
| - if (kind == Code::CALL_IC) {
|
| - CallIC::GenerateMiss(masm(), argc, extra_state);
|
| - } else {
|
| - KeyedCallIC::GenerateMiss(masm(), argc);
|
| - }
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
|
| - isolate()->counters()->call_megamorphic_stubs()->Increment();
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
|
| - *code, code->arguments_count()));
|
| - GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
|
| - return code;
|
| -}
|
| -
|
| -
|
| -#ifdef ENABLE_DEBUGGER_SUPPORT
|
| -Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
|
| - Debug::GenerateCallICDebugBreak(masm());
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
|
| - CALL_DEBUG_BREAK_TAG),
|
| - *code, code->arguments_count()));
|
| - return code;
|
| -}
|
| -
|
| -
|
| -Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
|
| - // Use the same code for the the step in preparations as we do for the
|
| - // miss case.
|
| - int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
| - Code::Kind kind = Code::ExtractKindFromFlags(flags);
|
| - if (kind == Code::CALL_IC) {
|
| - // For the debugger extra ic state is irrelevant.
|
| - CallIC::GenerateMiss(masm(), argc, kNoExtraICState);
|
| - } else {
|
| - KeyedCallIC::GenerateMiss(masm(), argc);
|
| - }
|
| - Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(
|
| - CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
|
| - *code,
|
| - code->arguments_count()));
|
| - return code;
|
| -}
|
| -#endif // ENABLE_DEBUGGER_SUPPORT
|
| -
|
| #undef CALL_LOGGER_TAG
|
|
|
|
|
| @@ -1251,77 +782,21 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
|
| #define __ ACCESS_MASM(masm())
|
|
|
|
|
| -void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
|
| - __ bind(miss);
|
| - GenerateMissBranch();
|
| -}
|
| -
|
| -
|
| -void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver(
|
| - Handle<JSFunction> function) {
|
| - ParameterCount expected(function);
|
| - __ InvokeFunction(function, expected, arguments(),
|
| - JUMP_FUNCTION, NullCallWrapper());
|
| -}
|
| -
|
| -
|
| -void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
|
| - Handle<JSFunction> function) {
|
| - PatchImplicitReceiver(object);
|
| - GenerateJumpFunctionIgnoreReceiver(function);
|
| -}
|
| -
|
| -
|
| -void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
|
| - Register actual_closure,
|
| - Handle<JSFunction> function) {
|
| - PatchImplicitReceiver(object);
|
| - ParameterCount expected(function);
|
| - __ InvokeFunction(actual_closure, expected, arguments(),
|
| - JUMP_FUNCTION, NullCallWrapper());
|
| -}
|
| -
|
| -
|
| -Handle<Code> CallStubCompiler::CompileCallConstant(
|
| - Handle<Object> object,
|
| - Handle<JSObject> holder,
|
| - Handle<Name> name,
|
| - CheckType check,
|
| - Handle<JSFunction> function) {
|
| - if (HasCustomCallGenerator(function)) {
|
| - Handle<Code> code = CompileCustomCall(object, holder,
|
| - Handle<Cell>::null(),
|
| - function, Handle<String>::cast(name),
|
| - Code::FAST);
|
| - // A null handle means bail out to the regular compiler code below.
|
| - if (!code.is_null()) return code;
|
| - }
|
| -
|
| - Label miss;
|
| - HandlerFrontendHeader(object, holder, name, check, &miss);
|
| - GenerateJumpFunction(object, function);
|
| - HandlerFrontendFooter(&miss);
|
| -
|
| - // Return the generated code.
|
| - return GetCode(function);
|
| -}
|
| -
|
| -
|
| Register LoadStubCompiler::HandlerFrontendHeader(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Register object_reg,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| Label* miss) {
|
| PrototypeCheckType check_type = CHECK_ALL_MAPS;
|
| int function_index = -1;
|
| - if (type->Is(Type::String())) {
|
| + if (type->Is(HeapType::String())) {
|
| function_index = Context::STRING_FUNCTION_INDEX;
|
| - } else if (type->Is(Type::Symbol())) {
|
| + } else if (type->Is(HeapType::Symbol())) {
|
| function_index = Context::SYMBOL_FUNCTION_INDEX;
|
| - } else if (type->Is(Type::Number())) {
|
| + } else if (type->Is(HeapType::Number())) {
|
| function_index = Context::NUMBER_FUNCTION_INDEX;
|
| - } else if (type->Is(Type::Boolean())) {
|
| + } else if (type->Is(HeapType::Boolean())) {
|
| // Booleans use the generic oddball map, so an additional check is needed to
|
| // ensure the receiver is really a boolean.
|
| GenerateBooleanCheck(object_reg, miss);
|
| @@ -1349,7 +824,7 @@ Register LoadStubCompiler::HandlerFrontendHeader(
|
| // HandlerFrontend for store uses the name register. It has to be restored
|
| // before a miss.
|
| Register StoreStubCompiler::HandlerFrontendHeader(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Register object_reg,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| @@ -1361,13 +836,13 @@ Register StoreStubCompiler::HandlerFrontendHeader(
|
|
|
| bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) {
|
| for (int i = 0; i < types->length(); ++i) {
|
| - if (types->at(i)->Is(Type::Number())) return true;
|
| + if (types->at(i)->Is(HeapType::Number())) return true;
|
| }
|
| return false;
|
| }
|
|
|
|
|
| -Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Type> type,
|
| +Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<HeapType> type,
|
| Register object_reg,
|
| Handle<JSObject> holder,
|
| Handle<Name> name) {
|
| @@ -1381,7 +856,7 @@ Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Type> type,
|
| }
|
|
|
|
|
| -void LoadStubCompiler::NonexistentHandlerFrontend(Handle<Type> type,
|
| +void LoadStubCompiler::NonexistentHandlerFrontend(Handle<HeapType> type,
|
| Handle<JSObject> last,
|
| Handle<Name> name) {
|
| Label miss;
|
| @@ -1426,27 +901,21 @@ void LoadStubCompiler::NonexistentHandlerFrontend(Handle<Type> type,
|
|
|
|
|
| Handle<Code> LoadStubCompiler::CompileLoadField(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| PropertyIndex field,
|
| Representation representation) {
|
| - Label miss;
|
| -
|
| - Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss);
|
| -
|
| + Register reg = HandlerFrontend(type, receiver(), holder, name);
|
| GenerateLoadField(reg, holder, field, representation);
|
|
|
| - __ bind(&miss);
|
| - TailCallBuiltin(masm(), MissBuiltin(kind()));
|
| -
|
| // Return the generated code.
|
| return GetCode(kind(), Code::FAST, name);
|
| }
|
|
|
|
|
| Handle<Code> LoadStubCompiler::CompileLoadConstant(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| Handle<Object> value) {
|
| @@ -1459,7 +928,7 @@ Handle<Code> LoadStubCompiler::CompileLoadConstant(
|
|
|
|
|
| Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| Handle<ExecutableAccessorInfo> callback) {
|
| @@ -1473,22 +942,24 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
|
|
|
|
| Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| const CallOptimization& call_optimization) {
|
| ASSERT(call_optimization.is_simple_api_call());
|
| Handle<JSFunction> callback = call_optimization.constant_function();
|
| CallbackHandlerFrontend(type, receiver(), holder, name, callback);
|
| - GenerateLoadCallback(call_optimization);
|
| -
|
| + Handle<Map>receiver_map = IC::TypeToMap(*type, isolate());
|
| + GenerateFastApiCall(
|
| + masm(), call_optimization, receiver_map,
|
| + receiver(), scratch1(), false, 0, NULL);
|
| // Return the generated code.
|
| return GetCode(kind(), Code::FAST, name);
|
| }
|
|
|
|
|
| Handle<Code> LoadStubCompiler::CompileLoadInterceptor(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<JSObject> holder,
|
| Handle<Name> name) {
|
| LookupResult lookup(isolate());
|
| @@ -1541,7 +1012,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor(
|
|
|
|
|
| Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<Code> handler,
|
| Handle<Name> name) {
|
| TypeHandleList types(1);
|
| @@ -1554,12 +1025,12 @@ Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC(
|
|
|
|
|
| Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
|
| - Handle<Type> type,
|
| + Handle<HeapType> type,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| Handle<JSFunction> getter) {
|
| HandlerFrontend(type, receiver(), holder, name);
|
| - GenerateLoadViaGetter(masm(), receiver(), getter);
|
| + GenerateLoadViaGetter(masm(), type, receiver(), getter);
|
|
|
| // Return the generated code.
|
| return GetCode(kind(), Code::FAST, name);
|
| @@ -1652,10 +1123,26 @@ Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| Handle<JSFunction> setter) {
|
| + Handle<HeapType> type = IC::CurrentTypeOf(object, isolate());
|
| + HandlerFrontend(type, receiver(), holder, name);
|
| + GenerateStoreViaSetter(masm(), type, setter);
|
| +
|
| + return GetCode(kind(), Code::FAST, name);
|
| +}
|
| +
|
| +
|
| +Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
| + Handle<JSObject> object,
|
| + Handle<JSObject> holder,
|
| + Handle<Name> name,
|
| + const CallOptimization& call_optimization) {
|
| HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
|
| receiver(), holder, name);
|
| - GenerateStoreViaSetter(masm(), setter);
|
| -
|
| + Register values[] = { value() };
|
| + GenerateFastApiCall(
|
| + masm(), call_optimization, handle(object->map()),
|
| + receiver(), scratch1(), true, 1, values);
|
| + // Return the generated code.
|
| return GetCode(kind(), Code::FAST, name);
|
| }
|
|
|
| @@ -1765,8 +1252,8 @@ Handle<Code> BaseLoadStoreStubCompiler::GetICCode(Code::Kind kind,
|
| Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind,
|
| Code::StubType type,
|
| Handle<Name> name) {
|
| - Code::Flags flags = Code::ComputeFlags(
|
| - Code::HANDLER, MONOMORPHIC, extra_state(), type, kind, cache_holder_);
|
| + ASSERT_EQ(kNoExtraICState, extra_state());
|
| + Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder_);
|
| Handle<Code> code = GetCodeWithFlags(flags, name);
|
| PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
|
| JitEvent(name, code);
|
| @@ -1865,83 +1352,6 @@ void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
|
| }
|
|
|
|
|
| -CallStubCompiler::CallStubCompiler(Isolate* isolate,
|
| - int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state,
|
| - InlineCacheHolderFlag cache_holder)
|
| - : StubCompiler(isolate, extra_state),
|
| - arguments_(argc),
|
| - kind_(kind),
|
| - cache_holder_(cache_holder) {
|
| -}
|
| -
|
| -
|
| -bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
|
| - if (function->shared()->HasBuiltinFunctionId()) {
|
| - BuiltinFunctionId id = function->shared()->builtin_function_id();
|
| -#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
|
| - CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
|
| -#undef CALL_GENERATOR_CASE
|
| - }
|
| -
|
| - CallOptimization optimization(function);
|
| - return optimization.is_simple_api_call();
|
| -}
|
| -
|
| -
|
| -Handle<Code> CallStubCompiler::CompileCustomCall(
|
| - Handle<Object> object,
|
| - Handle<JSObject> holder,
|
| - Handle<Cell> cell,
|
| - Handle<JSFunction> function,
|
| - Handle<String> fname,
|
| - Code::StubType type) {
|
| - ASSERT(HasCustomCallGenerator(function));
|
| -
|
| - if (function->shared()->HasBuiltinFunctionId()) {
|
| - BuiltinFunctionId id = function->shared()->builtin_function_id();
|
| -#define CALL_GENERATOR_CASE(name) \
|
| - if (id == k##name) { \
|
| - return CallStubCompiler::Compile##name##Call(object, \
|
| - holder, \
|
| - cell, \
|
| - function, \
|
| - fname, \
|
| - type); \
|
| - }
|
| - CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
|
| -#undef CALL_GENERATOR_CASE
|
| - }
|
| - CallOptimization optimization(function);
|
| - ASSERT(optimization.is_simple_api_call());
|
| - return CompileFastApiCall(optimization,
|
| - object,
|
| - holder,
|
| - cell,
|
| - function,
|
| - fname);
|
| -}
|
| -
|
| -
|
| -Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
|
| - Handle<Name> name) {
|
| - int argc = arguments_.immediate();
|
| - Code::Flags flags = Code::ComputeMonomorphicFlags(
|
| - kind_, extra_state(), cache_holder_, type, argc);
|
| - return GetCodeWithFlags(flags, name);
|
| -}
|
| -
|
| -
|
| -Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
|
| - Handle<String> function_name;
|
| - if (function->shared()->name()->IsString()) {
|
| - function_name = Handle<String>(String::cast(function->shared()->name()));
|
| - }
|
| - return GetCode(Code::FAST, function_name);
|
| -}
|
| -
|
| -
|
| CallOptimization::CallOptimization(LookupResult* lookup) {
|
| if (lookup->IsFound() &&
|
| lookup->IsCacheable() &&
|
| @@ -1959,20 +1369,63 @@ CallOptimization::CallOptimization(Handle<JSFunction> function) {
|
| }
|
|
|
|
|
| -int CallOptimization::GetPrototypeDepthOfExpectedType(
|
| - Handle<JSObject> object,
|
| - Handle<JSObject> holder) const {
|
| +Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
|
| + Handle<Map> object_map,
|
| + HolderLookup* holder_lookup) const {
|
| + ASSERT(is_simple_api_call());
|
| + if (!object_map->IsJSObjectMap()) {
|
| + *holder_lookup = kHolderNotFound;
|
| + return Handle<JSObject>::null();
|
| + }
|
| + if (expected_receiver_type_.is_null() ||
|
| + expected_receiver_type_->IsTemplateFor(*object_map)) {
|
| + *holder_lookup = kHolderIsReceiver;
|
| + return Handle<JSObject>::null();
|
| + }
|
| + while (true) {
|
| + if (!object_map->prototype()->IsJSObject()) break;
|
| + Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
|
| + if (!prototype->map()->is_hidden_prototype()) break;
|
| + object_map = handle(prototype->map());
|
| + if (expected_receiver_type_->IsTemplateFor(*object_map)) {
|
| + *holder_lookup = kHolderFound;
|
| + return prototype;
|
| + }
|
| + }
|
| + *holder_lookup = kHolderNotFound;
|
| + return Handle<JSObject>::null();
|
| +}
|
| +
|
| +
|
| +bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
|
| + Handle<JSObject> holder) const {
|
| ASSERT(is_simple_api_call());
|
| - if (expected_receiver_type_.is_null()) return 0;
|
| - int depth = 0;
|
| - while (!object.is_identical_to(holder)) {
|
| - if (expected_receiver_type_->IsTemplateFor(object->map())) return depth;
|
| - object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
|
| - if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth;
|
| - ++depth;
|
| + if (!receiver->IsJSObject()) return false;
|
| + Handle<Map> map(JSObject::cast(*receiver)->map());
|
| + HolderLookup holder_lookup;
|
| + Handle<JSObject> api_holder =
|
| + LookupHolderOfExpectedType(map, &holder_lookup);
|
| + switch (holder_lookup) {
|
| + case kHolderNotFound:
|
| + return false;
|
| + case kHolderIsReceiver:
|
| + return true;
|
| + case kHolderFound:
|
| + if (api_holder.is_identical_to(holder)) return true;
|
| + // Check if holder is in prototype chain of api_holder.
|
| + {
|
| + JSObject* object = *api_holder;
|
| + while (true) {
|
| + Object* prototype = object->map()->prototype();
|
| + if (!prototype->IsJSObject()) return false;
|
| + if (prototype == *holder) return true;
|
| + object = JSObject::cast(prototype);
|
| + }
|
| + }
|
| + break;
|
| }
|
| - if (expected_receiver_type_->IsTemplateFor(holder->map())) return depth;
|
| - return kInvalidProtoDepth;
|
| + UNREACHABLE();
|
| + return false;
|
| }
|
|
|
|
|
|
|