| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 Code::HANDLER, kNoExtraICState, cache_holder, Code::NORMAL, kind); | 121 Code::HANDLER, kNoExtraICState, cache_holder, Code::NORMAL, kind); |
| 122 | 122 |
| 123 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); | 123 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); |
| 124 if (probe->IsCode()) return Handle<Code>::cast(probe); | 124 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 125 return Handle<Code>::null(); | 125 return Handle<Code>::null(); |
| 126 } | 126 } |
| 127 | 127 |
| 128 | 128 |
| 129 Handle<Code> StubCache::ComputeMonomorphicIC( | 129 Handle<Code> StubCache::ComputeMonomorphicIC( |
| 130 Handle<Name> name, | 130 Handle<Name> name, |
| 131 Handle<Type> type, | 131 Handle<HeapType> type, |
| 132 Handle<Code> handler, | 132 Handle<Code> handler, |
| 133 ExtraICState extra_ic_state) { | 133 ExtraICState extra_ic_state) { |
| 134 Code::Kind kind = handler->handler_kind(); | 134 Code::Kind kind = handler->handler_kind(); |
| 135 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); | 135 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); |
| 136 | 136 |
| 137 Handle<Map> stub_holder; | 137 Handle<Map> stub_holder; |
| 138 Handle<Code> ic; | 138 Handle<Code> ic; |
| 139 // There are multiple string maps that all use the same prototype. That | 139 // There are multiple string maps that all use the same prototype. That |
| 140 // prototype cannot hold multiple handlers, one for each of the string maps, | 140 // prototype cannot hold multiple handlers, one for each of the string maps, |
| 141 // for a single name. Hence, turn off caching of the IC. | 141 // for a single name. Hence, turn off caching of the IC. |
| 142 bool can_be_cached = !type->Is(Type::String()); | 142 bool can_be_cached = !type->Is(HeapType::String()); |
| 143 if (can_be_cached) { | 143 if (can_be_cached) { |
| 144 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); | 144 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); |
| 145 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag); | 145 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag); |
| 146 if (!ic.is_null()) return ic; | 146 if (!ic.is_null()) return ic; |
| 147 } | 147 } |
| 148 | 148 |
| 149 if (kind == Code::LOAD_IC) { | 149 if (kind == Code::LOAD_IC) { |
| 150 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); | 150 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); |
| 151 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 151 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 152 } else if (kind == Code::KEYED_LOAD_IC) { | 152 } else if (kind == Code::KEYED_LOAD_IC) { |
| 153 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); | 153 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); |
| 154 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 154 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 155 } else if (kind == Code::STORE_IC) { | 155 } else if (kind == Code::STORE_IC) { |
| 156 StoreStubCompiler ic_compiler(isolate(), extra_ic_state); | 156 StoreStubCompiler ic_compiler(isolate(), extra_ic_state); |
| 157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 158 } else { | 158 } else { |
| 159 ASSERT(kind == Code::KEYED_STORE_IC); | 159 ASSERT(kind == Code::KEYED_STORE_IC); |
| 160 ASSERT(STANDARD_STORE == | 160 ASSERT(STANDARD_STORE == |
| 161 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); | 161 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); |
| 162 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state); | 162 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state); |
| 163 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 163 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 164 } | 164 } |
| 165 | 165 |
| 166 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | 166 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
| 167 return ic; | 167 return ic; |
| 168 } | 168 } |
| 169 | 169 |
| 170 | 170 |
| 171 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, | 171 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, |
| 172 Handle<Type> type) { | 172 Handle<HeapType> type) { |
| 173 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); | 173 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); |
| 174 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); | 174 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); |
| 175 // If no dictionary mode objects are present in the prototype chain, the load | 175 // If no dictionary mode objects are present in the prototype chain, the load |
| 176 // nonexistent IC stub can be shared for all names for a given map and we use | 176 // nonexistent IC stub can be shared for all names for a given map and we use |
| 177 // the empty string for the map cache in that case. If there are dictionary | 177 // the empty string for the map cache in that case. If there are dictionary |
| 178 // mode objects involved, we need to do negative lookups in the stub and | 178 // mode objects involved, we need to do negative lookups in the stub and |
| 179 // therefore the stub will be specific to the name. | 179 // therefore the stub will be specific to the name. |
| 180 Handle<Map> current_map = stub_holder; | 180 Handle<Map> current_map = stub_holder; |
| 181 Handle<Name> cache_name = current_map->is_dictionary_map() | 181 Handle<Name> cache_name = current_map->is_dictionary_map() |
| 182 ? name : Handle<Name>::cast(isolate()->factory()->empty_string()); | 182 ? name : Handle<Name>::cast(isolate()->factory()->empty_string()); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 | 290 |
| 291 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | 291 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); |
| 292 Handle<Code> code = | 292 Handle<Code> code = |
| 293 compiler.CompileCallConstant(object, holder, name, check, function); | 293 compiler.CompileCallConstant(object, holder, name, check, function); |
| 294 code->set_check_type(check); | 294 code->set_check_type(check); |
| 295 ASSERT(flags == code->flags()); | 295 ASSERT(flags == code->flags()); |
| 296 PROFILE(isolate_, | 296 PROFILE(isolate_, |
| 297 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 297 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 298 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 298 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 299 | 299 |
| 300 if (CallStubCompiler::CanBeCached(function)) { | 300 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 301 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | |
| 302 } | |
| 303 return code; | 301 return code; |
| 304 } | 302 } |
| 305 | 303 |
| 306 | 304 |
| 307 Handle<Code> StubCache::ComputeCallField(int argc, | 305 Handle<Code> StubCache::ComputeCallField(int argc, |
| 308 Code::Kind kind, | 306 Code::Kind kind, |
| 309 ExtraICState extra_state, | 307 ExtraICState extra_state, |
| 310 Handle<Name> name, | 308 Handle<Name> name, |
| 311 Handle<Object> object, | 309 Handle<Object> object, |
| 312 Handle<JSObject> holder, | 310 Handle<JSObject> holder, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 isolate_); | 393 isolate_); |
| 396 if (probe->IsCode()) return Handle<Code>::cast(probe); | 394 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 397 | 395 |
| 398 CallStubCompiler compiler(isolate(), argc, kind, extra_state); | 396 CallStubCompiler compiler(isolate(), argc, kind, extra_state); |
| 399 Handle<Code> code = | 397 Handle<Code> code = |
| 400 compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 398 compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
| 401 ASSERT(flags == code->flags()); | 399 ASSERT(flags == code->flags()); |
| 402 PROFILE(isolate(), | 400 PROFILE(isolate(), |
| 403 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 401 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 404 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 402 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 405 if (CallStubCompiler::CanBeCached(function)) { | 403 HeapObject::UpdateMapCodeCache(receiver, name, code); |
| 406 HeapObject::UpdateMapCodeCache(receiver, name, code); | |
| 407 } | |
| 408 return code; | 404 return code; |
| 409 } | 405 } |
| 410 | 406 |
| 411 | 407 |
| 412 static void FillCache(Isolate* isolate, Handle<Code> code) { | 408 static void FillCache(Isolate* isolate, Handle<Code> code) { |
| 413 Handle<UnseededNumberDictionary> dictionary = | 409 Handle<UnseededNumberDictionary> dictionary = |
| 414 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 410 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
| 415 code->flags(), | 411 code->flags(), |
| 416 code); | 412 code); |
| 417 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 413 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
| 418 } | 414 } |
| 419 | 415 |
| 420 | 416 |
| 421 Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) { | 417 Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) { |
| 422 ExtraICState extra_state = | 418 Code::Flags flags = Code::ComputeFlags( |
| 423 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB); | 419 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc); |
| 424 Code::Flags flags = | |
| 425 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc); | |
| 426 UnseededNumberDictionary* dictionary = | 420 UnseededNumberDictionary* dictionary = |
| 427 isolate()->heap()->non_monomorphic_cache(); | 421 isolate()->heap()->non_monomorphic_cache(); |
| 428 int entry = dictionary->FindEntry(isolate(), flags); | 422 int entry = dictionary->FindEntry(isolate(), flags); |
| 429 ASSERT(entry != -1); | 423 ASSERT(entry != -1); |
| 430 Object* code = dictionary->ValueAt(entry); | 424 Object* code = dictionary->ValueAt(entry); |
| 431 // This might be called during the marking phase of the collector | 425 // This might be called during the marking phase of the collector |
| 432 // hence the unchecked cast. | 426 // hence the unchecked cast. |
| 433 return reinterpret_cast<Code*>(code); | 427 return reinterpret_cast<Code*>(code); |
| 434 } | 428 } |
| 435 | 429 |
| 436 | 430 |
| 437 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { | 431 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { |
| 438 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 432 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
| 439 UnseededNumberDictionary* dictionary = | 433 UnseededNumberDictionary* dictionary = |
| 440 isolate()->heap()->non_monomorphic_cache(); | 434 isolate()->heap()->non_monomorphic_cache(); |
| 441 int entry = dictionary->FindEntry(isolate(), flags); | 435 int entry = dictionary->FindEntry(isolate(), flags); |
| 442 ASSERT(entry != -1); | 436 ASSERT(entry != -1); |
| 443 Object* code = dictionary->ValueAt(entry); | 437 Object* code = dictionary->ValueAt(entry); |
| 444 // This might be called during the marking phase of the collector | 438 // This might be called during the marking phase of the collector |
| 445 // hence the unchecked cast. | 439 // hence the unchecked cast. |
| 446 return reinterpret_cast<Code*>(code); | 440 return reinterpret_cast<Code*>(code); |
| 447 } | 441 } |
| 448 | 442 |
| 449 | 443 |
| 450 Handle<Code> StubCache::ComputeCallInitialize(int argc, Code::Kind kind) { | 444 Handle<Code> StubCache::ComputeCallInitialize(int argc, Code::Kind kind) { |
| 451 ExtraICState extra_state = | 445 Code::Flags flags = Code::ComputeFlags( |
| 452 CallICBase::ComputeExtraICState(DEFAULT_STRING_STUB); | 446 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc); |
| 453 Code::Flags flags = | |
| 454 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc); | |
| 455 Handle<UnseededNumberDictionary> cache = | 447 Handle<UnseededNumberDictionary> cache = |
| 456 isolate_->factory()->non_monomorphic_cache(); | 448 isolate_->factory()->non_monomorphic_cache(); |
| 457 int entry = cache->FindEntry(isolate_, flags); | 449 int entry = cache->FindEntry(isolate_, flags); |
| 458 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 450 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 459 | 451 |
| 460 StubCompiler compiler(isolate_); | 452 StubCompiler compiler(isolate_); |
| 461 Handle<Code> code = compiler.CompileCallInitialize(flags); | 453 Handle<Code> code = compiler.CompileCallInitialize(flags); |
| 462 FillCache(isolate_, code); | 454 FillCache(isolate_, code); |
| 463 return code; | 455 return code; |
| 464 } | 456 } |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 Handle<Code> StubCache::ComputeLoadElementPolymorphic( | 631 Handle<Code> StubCache::ComputeLoadElementPolymorphic( |
| 640 MapHandleList* receiver_maps) { | 632 MapHandleList* receiver_maps) { |
| 641 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 633 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
| 642 Handle<PolymorphicCodeCache> cache = | 634 Handle<PolymorphicCodeCache> cache = |
| 643 isolate_->factory()->polymorphic_code_cache(); | 635 isolate_->factory()->polymorphic_code_cache(); |
| 644 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 636 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 645 if (probe->IsCode()) return Handle<Code>::cast(probe); | 637 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 646 | 638 |
| 647 TypeHandleList types(receiver_maps->length()); | 639 TypeHandleList types(receiver_maps->length()); |
| 648 for (int i = 0; i < receiver_maps->length(); i++) { | 640 for (int i = 0; i < receiver_maps->length(); i++) { |
| 649 types.Add(Type::Class(receiver_maps->at(i), isolate())); | 641 types.Add(HeapType::Class(receiver_maps->at(i), isolate())); |
| 650 } | 642 } |
| 651 CodeHandleList handlers(receiver_maps->length()); | 643 CodeHandleList handlers(receiver_maps->length()); |
| 652 KeyedLoadStubCompiler compiler(isolate_); | 644 KeyedLoadStubCompiler compiler(isolate_); |
| 653 compiler.CompileElementHandlers(receiver_maps, &handlers); | 645 compiler.CompileElementHandlers(receiver_maps, &handlers); |
| 654 Handle<Code> code = compiler.CompilePolymorphicIC( | 646 Handle<Code> code = compiler.CompilePolymorphicIC( |
| 655 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); | 647 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); |
| 656 | 648 |
| 657 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 649 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 658 | 650 |
| 659 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 651 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 } | 795 } |
| 804 } | 796 } |
| 805 } | 797 } |
| 806 | 798 |
| 807 | 799 |
| 808 // ------------------------------------------------------------------------ | 800 // ------------------------------------------------------------------------ |
| 809 // StubCompiler implementation. | 801 // StubCompiler implementation. |
| 810 | 802 |
| 811 | 803 |
| 812 RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) { | 804 RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) { |
| 813 JSObject* recv = JSObject::cast(args[0]); | 805 JSObject* receiver = JSObject::cast(args[0]); |
| 814 ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[1]); | 806 JSObject* holder = JSObject::cast(args[1]); |
| 807 ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[2]); |
| 815 Address setter_address = v8::ToCData<Address>(callback->setter()); | 808 Address setter_address = v8::ToCData<Address>(callback->setter()); |
| 816 v8::AccessorSetterCallback fun = | 809 v8::AccessorSetterCallback fun = |
| 817 FUNCTION_CAST<v8::AccessorSetterCallback>(setter_address); | 810 FUNCTION_CAST<v8::AccessorSetterCallback>(setter_address); |
| 818 ASSERT(fun != NULL); | 811 ASSERT(fun != NULL); |
| 819 ASSERT(callback->IsCompatibleReceiver(recv)); | 812 ASSERT(callback->IsCompatibleReceiver(receiver)); |
| 820 Handle<Name> name = args.at<Name>(2); | 813 Handle<Name> name = args.at<Name>(3); |
| 821 Handle<Object> value = args.at<Object>(3); | 814 Handle<Object> value = args.at<Object>(4); |
| 822 HandleScope scope(isolate); | 815 HandleScope scope(isolate); |
| 823 | 816 |
| 824 // TODO(rossberg): Support symbols in the API. | 817 // TODO(rossberg): Support symbols in the API. |
| 825 if (name->IsSymbol()) return *value; | 818 if (name->IsSymbol()) return *value; |
| 826 Handle<String> str = Handle<String>::cast(name); | 819 Handle<String> str = Handle<String>::cast(name); |
| 827 | 820 |
| 828 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name)); | 821 LOG(isolate, ApiNamedPropertyAccess("store", receiver, *name)); |
| 829 PropertyCallbackArguments | 822 PropertyCallbackArguments |
| 830 custom_args(isolate, callback->data(), recv, recv); | 823 custom_args(isolate, callback->data(), receiver, holder); |
| 831 custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value)); | 824 custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value)); |
| 832 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 825 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 833 return *value; | 826 return *value; |
| 834 } | 827 } |
| 835 | 828 |
| 836 | 829 |
| 837 /** | 830 /** |
| 838 * Attempts to load a property with an interceptor (which must be present), | 831 * Attempts to load a property with an interceptor (which must be present), |
| 839 * but doesn't search the prototype chain. | 832 * but doesn't search the prototype chain. |
| 840 * | 833 * |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 return *v8::Utils::OpenHandle(*r); | 869 return *v8::Utils::OpenHandle(*r); |
| 877 } | 870 } |
| 878 } | 871 } |
| 879 | 872 |
| 880 return isolate->heap()->no_interceptor_result_sentinel(); | 873 return isolate->heap()->no_interceptor_result_sentinel(); |
| 881 } | 874 } |
| 882 | 875 |
| 883 | 876 |
| 884 static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) { | 877 static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) { |
| 885 // If the load is non-contextual, just return the undefined result. | 878 // If the load is non-contextual, just return the undefined result. |
| 886 // Note that both keyed and non-keyed loads may end up here, so we | 879 // Note that both keyed and non-keyed loads may end up here. |
| 887 // can't use either LoadIC or KeyedLoadIC constructors. | |
| 888 HandleScope scope(isolate); | 880 HandleScope scope(isolate); |
| 889 IC ic(IC::NO_EXTRA_FRAME, isolate); | 881 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 890 ASSERT(ic.IsLoadStub()); | 882 if (ic.contextual_mode() != CONTEXTUAL) { |
| 891 if (!ic.IsContextual()) { | |
| 892 return isolate->heap()->undefined_value(); | 883 return isolate->heap()->undefined_value(); |
| 893 } | 884 } |
| 894 | 885 |
| 895 // Throw a reference error. | 886 // Throw a reference error. |
| 896 Handle<Name> name_handle(name); | 887 Handle<Name> name_handle(name); |
| 897 Handle<Object> error = | 888 Handle<Object> error = |
| 898 isolate->factory()->NewReferenceError("not_defined", | 889 isolate->factory()->NewReferenceError("not_defined", |
| 899 HandleVector(&name_handle, 1)); | 890 HandleVector(&name_handle, 1)); |
| 900 return isolate->Throw(*error); | 891 return isolate->Throw(*error); |
| 901 } | 892 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 *code, code->arguments_count())); | 1031 *code, code->arguments_count())); |
| 1041 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code)); | 1032 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code)); |
| 1042 return code; | 1033 return code; |
| 1043 } | 1034 } |
| 1044 | 1035 |
| 1045 | 1036 |
| 1046 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) { | 1037 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) { |
| 1047 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1038 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1048 Code::Kind kind = Code::ExtractKindFromFlags(flags); | 1039 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1049 if (kind == Code::CALL_IC) { | 1040 if (kind == Code::CALL_IC) { |
| 1050 // Call normal is always with a explict receiver. | |
| 1051 ASSERT(!CallIC::Contextual::decode( | |
| 1052 Code::ExtractExtraICStateFromFlags(flags))); | |
| 1053 CallIC::GenerateNormal(masm(), argc); | 1041 CallIC::GenerateNormal(masm(), argc); |
| 1054 } else { | 1042 } else { |
| 1055 KeyedCallIC::GenerateNormal(masm(), argc); | 1043 KeyedCallIC::GenerateNormal(masm(), argc); |
| 1056 } | 1044 } |
| 1057 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal"); | 1045 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal"); |
| 1058 isolate()->counters()->call_normal_stubs()->Increment(); | 1046 isolate()->counters()->call_normal_stubs()->Increment(); |
| 1059 PROFILE(isolate(), | 1047 PROFILE(isolate(), |
| 1060 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), | 1048 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), |
| 1061 *code, code->arguments_count())); | 1049 *code, code->arguments_count())); |
| 1062 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code)); | 1050 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1098 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); | 1086 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); |
| 1099 PROFILE(isolate(), | 1087 PROFILE(isolate(), |
| 1100 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); | 1088 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); |
| 1101 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); | 1089 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); |
| 1102 return code; | 1090 return code; |
| 1103 } | 1091 } |
| 1104 | 1092 |
| 1105 | 1093 |
| 1106 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) { | 1094 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) { |
| 1107 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 1095 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
| 1108 ContextualMode mode = IC::GetContextualMode(extra_state); | 1096 ContextualMode mode = LoadIC::GetContextualMode(extra_state); |
| 1109 LoadIC::GenerateMegamorphic(masm(), mode); | 1097 LoadIC::GenerateMegamorphic(masm(), mode); |
| 1110 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); | 1098 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); |
| 1111 PROFILE(isolate(), | 1099 PROFILE(isolate(), |
| 1112 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); | 1100 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); |
| 1113 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); | 1101 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); |
| 1114 return code; | 1102 return code; |
| 1115 } | 1103 } |
| 1116 | 1104 |
| 1117 | 1105 |
| 1118 Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) { | 1106 Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | 1275 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 1288 Register actual_closure, | 1276 Register actual_closure, |
| 1289 Handle<JSFunction> function) { | 1277 Handle<JSFunction> function) { |
| 1290 PatchImplicitReceiver(object); | 1278 PatchImplicitReceiver(object); |
| 1291 ParameterCount expected(function); | 1279 ParameterCount expected(function); |
| 1292 __ InvokeFunction(actual_closure, expected, arguments(), | 1280 __ InvokeFunction(actual_closure, expected, arguments(), |
| 1293 JUMP_FUNCTION, NullCallWrapper()); | 1281 JUMP_FUNCTION, NullCallWrapper()); |
| 1294 } | 1282 } |
| 1295 | 1283 |
| 1296 | 1284 |
| 1285 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1286 Handle<Object> object, |
| 1287 Handle<JSObject> holder, |
| 1288 Handle<Cell> cell, |
| 1289 Handle<JSFunction> function, |
| 1290 Handle<String> name, |
| 1291 Code::StubType type) { |
| 1292 // If object is not an array or is observed or sealed, bail out to regular |
| 1293 // call. |
| 1294 if (!object->IsJSArray() || |
| 1295 !cell.is_null() || |
| 1296 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1297 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1298 return Handle<Code>::null(); |
| 1299 } |
| 1300 |
| 1301 Label miss; |
| 1302 |
| 1303 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1304 |
| 1305 Handle<Map> map(Handle<JSArray>::cast(object)->map()); |
| 1306 ElementsKind elements_kind = map->elements_kind(); |
| 1307 const int argc = arguments().immediate(); |
| 1308 |
| 1309 ArrayPushStub stub(elements_kind, argc); |
| 1310 Handle<Code> code = stub.GetCode(isolate()); |
| 1311 StubCompiler::GenerateTailCall(masm(), code); |
| 1312 |
| 1313 HandlerFrontendFooter(&miss); |
| 1314 |
| 1315 // Return the generated code. |
| 1316 return GetCode(type, name); |
| 1317 } |
| 1318 |
| 1319 |
| 1297 Handle<Code> CallStubCompiler::CompileCallConstant( | 1320 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 1298 Handle<Object> object, | 1321 Handle<Object> object, |
| 1299 Handle<JSObject> holder, | 1322 Handle<JSObject> holder, |
| 1300 Handle<Name> name, | 1323 Handle<Name> name, |
| 1301 CheckType check, | 1324 CheckType check, |
| 1302 Handle<JSFunction> function) { | 1325 Handle<JSFunction> function) { |
| 1303 if (HasCustomCallGenerator(function)) { | 1326 if (HasCustomCallGenerator(function)) { |
| 1304 Handle<Code> code = CompileCustomCall(object, holder, | 1327 Handle<Code> code = CompileCustomCall(object, holder, |
| 1305 Handle<Cell>::null(), | 1328 Handle<Cell>::null(), |
| 1306 function, Handle<String>::cast(name), | 1329 function, Handle<String>::cast(name), |
| 1307 Code::FAST); | 1330 Code::FAST); |
| 1308 // A null handle means bail out to the regular compiler code below. | 1331 // A null handle means bail out to the regular compiler code below. |
| 1309 if (!code.is_null()) return code; | 1332 if (!code.is_null()) return code; |
| 1310 } | 1333 } |
| 1311 | 1334 |
| 1312 Label miss; | 1335 Label miss; |
| 1313 HandlerFrontendHeader(object, holder, name, check, &miss); | 1336 HandlerFrontendHeader(object, holder, name, check, &miss); |
| 1314 GenerateJumpFunction(object, function); | 1337 GenerateJumpFunction(object, function); |
| 1315 HandlerFrontendFooter(&miss); | 1338 HandlerFrontendFooter(&miss); |
| 1316 | 1339 |
| 1317 // Return the generated code. | 1340 // Return the generated code. |
| 1318 return GetCode(function); | 1341 return GetCode(function); |
| 1319 } | 1342 } |
| 1320 | 1343 |
| 1321 | 1344 |
| 1322 Register LoadStubCompiler::HandlerFrontendHeader( | 1345 Register LoadStubCompiler::HandlerFrontendHeader( |
| 1323 Handle<Type> type, | 1346 Handle<HeapType> type, |
| 1324 Register object_reg, | 1347 Register object_reg, |
| 1325 Handle<JSObject> holder, | 1348 Handle<JSObject> holder, |
| 1326 Handle<Name> name, | 1349 Handle<Name> name, |
| 1327 Label* miss) { | 1350 Label* miss) { |
| 1328 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 1351 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
| 1329 int function_index = -1; | 1352 int function_index = -1; |
| 1330 if (type->Is(Type::String())) { | 1353 if (type->Is(HeapType::String())) { |
| 1331 function_index = Context::STRING_FUNCTION_INDEX; | 1354 function_index = Context::STRING_FUNCTION_INDEX; |
| 1332 } else if (type->Is(Type::Symbol())) { | 1355 } else if (type->Is(HeapType::Symbol())) { |
| 1333 function_index = Context::SYMBOL_FUNCTION_INDEX; | 1356 function_index = Context::SYMBOL_FUNCTION_INDEX; |
| 1334 } else if (type->Is(Type::Number())) { | 1357 } else if (type->Is(HeapType::Number())) { |
| 1335 function_index = Context::NUMBER_FUNCTION_INDEX; | 1358 function_index = Context::NUMBER_FUNCTION_INDEX; |
| 1336 } else if (type->Is(Type::Boolean())) { | 1359 } else if (type->Is(HeapType::Boolean())) { |
| 1337 // Booleans use the generic oddball map, so an additional check is needed to | 1360 // Booleans use the generic oddball map, so an additional check is needed to |
| 1338 // ensure the receiver is really a boolean. | 1361 // ensure the receiver is really a boolean. |
| 1339 GenerateBooleanCheck(object_reg, miss); | 1362 GenerateBooleanCheck(object_reg, miss); |
| 1340 function_index = Context::BOOLEAN_FUNCTION_INDEX; | 1363 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
| 1341 } else { | 1364 } else { |
| 1342 check_type = SKIP_RECEIVER; | 1365 check_type = SKIP_RECEIVER; |
| 1343 } | 1366 } |
| 1344 | 1367 |
| 1345 if (check_type == CHECK_ALL_MAPS) { | 1368 if (check_type == CHECK_ALL_MAPS) { |
| 1346 GenerateDirectLoadGlobalFunctionPrototype( | 1369 GenerateDirectLoadGlobalFunctionPrototype( |
| 1347 masm(), function_index, scratch1(), miss); | 1370 masm(), function_index, scratch1(), miss); |
| 1348 Object* function = isolate()->native_context()->get(function_index); | 1371 Object* function = isolate()->native_context()->get(function_index); |
| 1349 Object* prototype = JSFunction::cast(function)->instance_prototype(); | 1372 Object* prototype = JSFunction::cast(function)->instance_prototype(); |
| 1350 type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate()); | 1373 type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate()); |
| 1351 object_reg = scratch1(); | 1374 object_reg = scratch1(); |
| 1352 } | 1375 } |
| 1353 | 1376 |
| 1354 // Check that the maps starting from the prototype haven't changed. | 1377 // Check that the maps starting from the prototype haven't changed. |
| 1355 return CheckPrototypes( | 1378 return CheckPrototypes( |
| 1356 type, object_reg, holder, scratch1(), scratch2(), scratch3(), | 1379 type, object_reg, holder, scratch1(), scratch2(), scratch3(), |
| 1357 name, miss, check_type); | 1380 name, miss, check_type); |
| 1358 } | 1381 } |
| 1359 | 1382 |
| 1360 | 1383 |
| 1361 // HandlerFrontend for store uses the name register. It has to be restored | 1384 // HandlerFrontend for store uses the name register. It has to be restored |
| 1362 // before a miss. | 1385 // before a miss. |
| 1363 Register StoreStubCompiler::HandlerFrontendHeader( | 1386 Register StoreStubCompiler::HandlerFrontendHeader( |
| 1364 Handle<Type> type, | 1387 Handle<HeapType> type, |
| 1365 Register object_reg, | 1388 Register object_reg, |
| 1366 Handle<JSObject> holder, | 1389 Handle<JSObject> holder, |
| 1367 Handle<Name> name, | 1390 Handle<Name> name, |
| 1368 Label* miss) { | 1391 Label* miss) { |
| 1369 return CheckPrototypes(type, object_reg, holder, this->name(), | 1392 return CheckPrototypes(type, object_reg, holder, this->name(), |
| 1370 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); | 1393 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); |
| 1371 } | 1394 } |
| 1372 | 1395 |
| 1373 | 1396 |
| 1374 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { | 1397 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { |
| 1375 for (int i = 0; i < types->length(); ++i) { | 1398 for (int i = 0; i < types->length(); ++i) { |
| 1376 if (types->at(i)->Is(Type::Number())) return true; | 1399 if (types->at(i)->Is(HeapType::Number())) return true; |
| 1377 } | 1400 } |
| 1378 return false; | 1401 return false; |
| 1379 } | 1402 } |
| 1380 | 1403 |
| 1381 | 1404 |
| 1382 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Type> type, | 1405 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<HeapType> type, |
| 1383 Register object_reg, | 1406 Register object_reg, |
| 1384 Handle<JSObject> holder, | 1407 Handle<JSObject> holder, |
| 1385 Handle<Name> name) { | 1408 Handle<Name> name) { |
| 1386 Label miss; | 1409 Label miss; |
| 1387 | 1410 |
| 1388 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 1411 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1389 | 1412 |
| 1390 HandlerFrontendFooter(name, &miss); | 1413 HandlerFrontendFooter(name, &miss); |
| 1391 | 1414 |
| 1392 return reg; | 1415 return reg; |
| 1393 } | 1416 } |
| 1394 | 1417 |
| 1395 | 1418 |
| 1396 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<Type> type, | 1419 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<HeapType> type, |
| 1397 Handle<JSObject> last, | 1420 Handle<JSObject> last, |
| 1398 Handle<Name> name) { | 1421 Handle<Name> name) { |
| 1399 Label miss; | 1422 Label miss; |
| 1400 | 1423 |
| 1401 Register holder; | 1424 Register holder; |
| 1402 Handle<Map> last_map; | 1425 Handle<Map> last_map; |
| 1403 if (last.is_null()) { | 1426 if (last.is_null()) { |
| 1404 holder = receiver(); | 1427 holder = receiver(); |
| 1405 last_map = IC::TypeToMap(*type, isolate()); | 1428 last_map = IC::TypeToMap(*type, isolate()); |
| 1406 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). | 1429 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1431 ? Handle<JSGlobalObject>::cast(type->AsConstant()) | 1454 ? Handle<JSGlobalObject>::cast(type->AsConstant()) |
| 1432 : Handle<JSGlobalObject>::cast(last); | 1455 : Handle<JSGlobalObject>::cast(last); |
| 1433 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1456 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1434 } | 1457 } |
| 1435 | 1458 |
| 1436 HandlerFrontendFooter(name, &miss); | 1459 HandlerFrontendFooter(name, &miss); |
| 1437 } | 1460 } |
| 1438 | 1461 |
| 1439 | 1462 |
| 1440 Handle<Code> LoadStubCompiler::CompileLoadField( | 1463 Handle<Code> LoadStubCompiler::CompileLoadField( |
| 1441 Handle<Type> type, | 1464 Handle<HeapType> type, |
| 1442 Handle<JSObject> holder, | 1465 Handle<JSObject> holder, |
| 1443 Handle<Name> name, | 1466 Handle<Name> name, |
| 1444 PropertyIndex field, | 1467 PropertyIndex field, |
| 1445 Representation representation) { | 1468 Representation representation) { |
| 1446 Label miss; | 1469 Label miss; |
| 1447 | 1470 |
| 1448 Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss); | 1471 Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss); |
| 1449 | 1472 |
| 1450 GenerateLoadField(reg, holder, field, representation); | 1473 GenerateLoadField(reg, holder, field, representation); |
| 1451 | 1474 |
| 1452 __ bind(&miss); | 1475 __ bind(&miss); |
| 1453 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1476 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1454 | 1477 |
| 1455 // Return the generated code. | 1478 // Return the generated code. |
| 1456 return GetCode(kind(), Code::FAST, name); | 1479 return GetCode(kind(), Code::FAST, name); |
| 1457 } | 1480 } |
| 1458 | 1481 |
| 1459 | 1482 |
| 1460 Handle<Code> LoadStubCompiler::CompileLoadConstant( | 1483 Handle<Code> LoadStubCompiler::CompileLoadConstant( |
| 1461 Handle<Type> type, | 1484 Handle<HeapType> type, |
| 1462 Handle<JSObject> holder, | 1485 Handle<JSObject> holder, |
| 1463 Handle<Name> name, | 1486 Handle<Name> name, |
| 1464 Handle<Object> value) { | 1487 Handle<Object> value) { |
| 1465 HandlerFrontend(type, receiver(), holder, name); | 1488 HandlerFrontend(type, receiver(), holder, name); |
| 1466 GenerateLoadConstant(value); | 1489 GenerateLoadConstant(value); |
| 1467 | 1490 |
| 1468 // Return the generated code. | 1491 // Return the generated code. |
| 1469 return GetCode(kind(), Code::FAST, name); | 1492 return GetCode(kind(), Code::FAST, name); |
| 1470 } | 1493 } |
| 1471 | 1494 |
| 1472 | 1495 |
| 1473 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 1496 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1474 Handle<Type> type, | 1497 Handle<HeapType> type, |
| 1475 Handle<JSObject> holder, | 1498 Handle<JSObject> holder, |
| 1476 Handle<Name> name, | 1499 Handle<Name> name, |
| 1477 Handle<ExecutableAccessorInfo> callback) { | 1500 Handle<ExecutableAccessorInfo> callback) { |
| 1478 Register reg = CallbackHandlerFrontend( | 1501 Register reg = CallbackHandlerFrontend( |
| 1479 type, receiver(), holder, name, callback); | 1502 type, receiver(), holder, name, callback); |
| 1480 GenerateLoadCallback(reg, callback); | 1503 GenerateLoadCallback(reg, callback); |
| 1481 | 1504 |
| 1482 // Return the generated code. | 1505 // Return the generated code. |
| 1483 return GetCode(kind(), Code::FAST, name); | 1506 return GetCode(kind(), Code::FAST, name); |
| 1484 } | 1507 } |
| 1485 | 1508 |
| 1486 | 1509 |
| 1487 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 1510 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1488 Handle<Type> type, | 1511 Handle<HeapType> type, |
| 1489 Handle<JSObject> holder, | 1512 Handle<JSObject> holder, |
| 1490 Handle<Name> name, | 1513 Handle<Name> name, |
| 1491 const CallOptimization& call_optimization) { | 1514 const CallOptimization& call_optimization) { |
| 1492 ASSERT(call_optimization.is_simple_api_call()); | 1515 ASSERT(call_optimization.is_simple_api_call()); |
| 1493 Handle<JSFunction> callback = call_optimization.constant_function(); | 1516 Handle<JSFunction> callback = call_optimization.constant_function(); |
| 1494 CallbackHandlerFrontend(type, receiver(), holder, name, callback); | 1517 CallbackHandlerFrontend(type, receiver(), holder, name, callback); |
| 1495 GenerateLoadCallback(call_optimization); | 1518 GenerateLoadCallback(call_optimization); |
| 1496 | 1519 |
| 1497 // Return the generated code. | 1520 // Return the generated code. |
| 1498 return GetCode(kind(), Code::FAST, name); | 1521 return GetCode(kind(), Code::FAST, name); |
| 1499 } | 1522 } |
| 1500 | 1523 |
| 1501 | 1524 |
| 1502 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( | 1525 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( |
| 1503 Handle<Type> type, | 1526 Handle<HeapType> type, |
| 1504 Handle<JSObject> holder, | 1527 Handle<JSObject> holder, |
| 1505 Handle<Name> name) { | 1528 Handle<Name> name) { |
| 1506 LookupResult lookup(isolate()); | 1529 LookupResult lookup(isolate()); |
| 1507 LookupPostInterceptor(holder, name, &lookup); | 1530 LookupPostInterceptor(holder, name, &lookup); |
| 1508 | 1531 |
| 1509 Register reg = HandlerFrontend(type, receiver(), holder, name); | 1532 Register reg = HandlerFrontend(type, receiver(), holder, name); |
| 1510 // TODO(368): Compile in the whole chain: all the interceptors in | 1533 // TODO(368): Compile in the whole chain: all the interceptors in |
| 1511 // prototypes and ultimate answer. | 1534 // prototypes and ultimate answer. |
| 1512 GenerateLoadInterceptor(reg, type, holder, &lookup, name); | 1535 GenerateLoadInterceptor(reg, type, holder, &lookup, name); |
| 1513 | 1536 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 | 1569 |
| 1547 Register reg = CallbackHandlerFrontend( | 1570 Register reg = CallbackHandlerFrontend( |
| 1548 IC::CurrentTypeOf(interceptor_holder, isolate()), | 1571 IC::CurrentTypeOf(interceptor_holder, isolate()), |
| 1549 interceptor_reg, holder, name, callback); | 1572 interceptor_reg, holder, name, callback); |
| 1550 GenerateLoadCallback(reg, callback); | 1573 GenerateLoadCallback(reg, callback); |
| 1551 } | 1574 } |
| 1552 } | 1575 } |
| 1553 | 1576 |
| 1554 | 1577 |
| 1555 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( | 1578 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( |
| 1556 Handle<Type> type, | 1579 Handle<HeapType> type, |
| 1557 Handle<Code> handler, | 1580 Handle<Code> handler, |
| 1558 Handle<Name> name) { | 1581 Handle<Name> name) { |
| 1559 TypeHandleList types(1); | 1582 TypeHandleList types(1); |
| 1560 CodeHandleList handlers(1); | 1583 CodeHandleList handlers(1); |
| 1561 types.Add(type); | 1584 types.Add(type); |
| 1562 handlers.Add(handler); | 1585 handlers.Add(handler); |
| 1563 Code::StubType stub_type = handler->type(); | 1586 Code::StubType stub_type = handler->type(); |
| 1564 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); | 1587 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); |
| 1565 } | 1588 } |
| 1566 | 1589 |
| 1567 | 1590 |
| 1568 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( | 1591 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( |
| 1569 Handle<Type> type, | 1592 Handle<HeapType> type, |
| 1570 Handle<JSObject> holder, | 1593 Handle<JSObject> holder, |
| 1571 Handle<Name> name, | 1594 Handle<Name> name, |
| 1572 Handle<JSFunction> getter) { | 1595 Handle<JSFunction> getter) { |
| 1573 HandlerFrontend(type, receiver(), holder, name); | 1596 HandlerFrontend(type, receiver(), holder, name); |
| 1574 GenerateLoadViaGetter(masm(), receiver(), getter); | 1597 GenerateLoadViaGetter(masm(), receiver(), getter); |
| 1575 | 1598 |
| 1576 // Return the generated code. | 1599 // Return the generated code. |
| 1577 return GetCode(kind(), Code::FAST, name); | 1600 return GetCode(kind(), Code::FAST, name); |
| 1578 } | 1601 } |
| 1579 | 1602 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1669 GenerateStoreViaSetter(masm(), setter); | 1692 GenerateStoreViaSetter(masm(), setter); |
| 1670 | 1693 |
| 1671 return GetCode(kind(), Code::FAST, name); | 1694 return GetCode(kind(), Code::FAST, name); |
| 1672 } | 1695 } |
| 1673 | 1696 |
| 1674 | 1697 |
| 1675 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 1698 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 1676 Handle<Map> receiver_map) { | 1699 Handle<Map> receiver_map) { |
| 1677 ElementsKind elements_kind = receiver_map->elements_kind(); | 1700 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1678 if (receiver_map->has_fast_elements() || | 1701 if (receiver_map->has_fast_elements() || |
| 1679 receiver_map->has_external_array_elements()) { | 1702 receiver_map->has_external_array_elements() || |
| 1703 receiver_map->has_fixed_typed_array_elements()) { |
| 1680 Handle<Code> stub = KeyedLoadFastElementStub( | 1704 Handle<Code> stub = KeyedLoadFastElementStub( |
| 1681 receiver_map->instance_type() == JS_ARRAY_TYPE, | 1705 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 1682 elements_kind).GetCode(isolate()); | 1706 elements_kind).GetCode(isolate()); |
| 1683 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | 1707 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); |
| 1684 } else { | 1708 } else { |
| 1685 Handle<Code> stub = FLAG_compiled_keyed_dictionary_loads | 1709 Handle<Code> stub = FLAG_compiled_keyed_dictionary_loads |
| 1686 ? KeyedLoadDictionaryElementStub().GetCode(isolate()) | 1710 ? KeyedLoadDictionaryElementStub().GetCode(isolate()) |
| 1687 : KeyedLoadDictionaryElementPlatformStub().GetCode(isolate()); | 1711 : KeyedLoadDictionaryElementPlatformStub().GetCode(isolate()); |
| 1688 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | 1712 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); |
| 1689 } | 1713 } |
| 1690 | 1714 |
| 1691 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss); | 1715 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss); |
| 1692 | 1716 |
| 1693 // Return the generated code. | 1717 // Return the generated code. |
| 1694 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); | 1718 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
| 1695 } | 1719 } |
| 1696 | 1720 |
| 1697 | 1721 |
| 1698 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( | 1722 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
| 1699 Handle<Map> receiver_map) { | 1723 Handle<Map> receiver_map) { |
| 1700 ElementsKind elements_kind = receiver_map->elements_kind(); | 1724 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1701 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1725 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1702 Handle<Code> stub; | 1726 Handle<Code> stub; |
| 1703 if (receiver_map->has_fast_elements() || | 1727 if (receiver_map->has_fast_elements() || |
| 1704 receiver_map->has_external_array_elements()) { | 1728 receiver_map->has_external_array_elements() || |
| 1729 receiver_map->has_fixed_typed_array_elements()) { |
| 1705 stub = KeyedStoreFastElementStub( | 1730 stub = KeyedStoreFastElementStub( |
| 1706 is_jsarray, | 1731 is_jsarray, |
| 1707 elements_kind, | 1732 elements_kind, |
| 1708 store_mode()).GetCode(isolate()); | 1733 store_mode()).GetCode(isolate()); |
| 1709 } else { | 1734 } else { |
| 1710 stub = KeyedStoreElementStub(is_jsarray, | 1735 stub = KeyedStoreElementStub(is_jsarray, |
| 1711 elements_kind, | 1736 elements_kind, |
| 1712 store_mode()).GetCode(isolate()); | 1737 store_mode()).GetCode(isolate()); |
| 1713 } | 1738 } |
| 1714 | 1739 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1792 | 1817 |
| 1793 if ((receiver_map->instance_type() & kNotStringTag) == 0) { | 1818 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
| 1794 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); | 1819 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); |
| 1795 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { | 1820 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { |
| 1796 cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); | 1821 cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); |
| 1797 } else { | 1822 } else { |
| 1798 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1823 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1799 ElementsKind elements_kind = receiver_map->elements_kind(); | 1824 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1800 | 1825 |
| 1801 if (IsFastElementsKind(elements_kind) || | 1826 if (IsFastElementsKind(elements_kind) || |
| 1802 IsExternalArrayElementsKind(elements_kind)) { | 1827 IsExternalArrayElementsKind(elements_kind) || |
| 1828 IsFixedTypedArrayElementsKind(elements_kind)) { |
| 1803 cached_stub = | 1829 cached_stub = |
| 1804 KeyedLoadFastElementStub(is_js_array, | 1830 KeyedLoadFastElementStub(is_js_array, |
| 1805 elements_kind).GetCode(isolate()); | 1831 elements_kind).GetCode(isolate()); |
| 1806 } else { | 1832 } else { |
| 1807 ASSERT(elements_kind == DICTIONARY_ELEMENTS); | 1833 ASSERT(elements_kind == DICTIONARY_ELEMENTS); |
| 1808 cached_stub = KeyedLoadDictionaryElementStub().GetCode(isolate()); | 1834 cached_stub = KeyedLoadDictionaryElementStub().GetCode(isolate()); |
| 1809 } | 1835 } |
| 1810 } | 1836 } |
| 1811 | 1837 |
| 1812 handlers->Add(cached_stub); | 1838 handlers->Add(cached_stub); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1835 if (!transitioned_map.is_null()) { | 1861 if (!transitioned_map.is_null()) { |
| 1836 cached_stub = ElementsTransitionAndStoreStub( | 1862 cached_stub = ElementsTransitionAndStoreStub( |
| 1837 elements_kind, | 1863 elements_kind, |
| 1838 transitioned_map->elements_kind(), | 1864 transitioned_map->elements_kind(), |
| 1839 is_js_array, | 1865 is_js_array, |
| 1840 store_mode()).GetCode(isolate()); | 1866 store_mode()).GetCode(isolate()); |
| 1841 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { | 1867 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { |
| 1842 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow(); | 1868 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow(); |
| 1843 } else { | 1869 } else { |
| 1844 if (receiver_map->has_fast_elements() || | 1870 if (receiver_map->has_fast_elements() || |
| 1845 receiver_map->has_external_array_elements()) { | 1871 receiver_map->has_external_array_elements() || |
| 1872 receiver_map->has_fixed_typed_array_elements()) { |
| 1846 cached_stub = KeyedStoreFastElementStub( | 1873 cached_stub = KeyedStoreFastElementStub( |
| 1847 is_js_array, | 1874 is_js_array, |
| 1848 elements_kind, | 1875 elements_kind, |
| 1849 store_mode()).GetCode(isolate()); | 1876 store_mode()).GetCode(isolate()); |
| 1850 } else { | 1877 } else { |
| 1851 cached_stub = KeyedStoreElementStub( | 1878 cached_stub = KeyedStoreElementStub( |
| 1852 is_js_array, | 1879 is_js_array, |
| 1853 elements_kind, | 1880 elements_kind, |
| 1854 store_mode()).GetCode(isolate()); | 1881 store_mode()).GetCode(isolate()); |
| 1855 } | 1882 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1891 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true; | 1918 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true; |
| 1892 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1919 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) |
| 1893 #undef CALL_GENERATOR_CASE | 1920 #undef CALL_GENERATOR_CASE |
| 1894 } | 1921 } |
| 1895 | 1922 |
| 1896 CallOptimization optimization(function); | 1923 CallOptimization optimization(function); |
| 1897 return optimization.is_simple_api_call(); | 1924 return optimization.is_simple_api_call(); |
| 1898 } | 1925 } |
| 1899 | 1926 |
| 1900 | 1927 |
| 1901 bool CallStubCompiler::CanBeCached(Handle<JSFunction> function) { | |
| 1902 if (function->shared()->HasBuiltinFunctionId()) { | |
| 1903 BuiltinFunctionId id = function->shared()->builtin_function_id(); | |
| 1904 #define CALL_GENERATOR_CASE(name) if (id == k##name) return false; | |
| 1905 SITE_SPECIFIC_CALL_GENERATORS(CALL_GENERATOR_CASE) | |
| 1906 #undef CALL_GENERATOR_CASE | |
| 1907 } | |
| 1908 | |
| 1909 return true; | |
| 1910 } | |
| 1911 | |
| 1912 | |
| 1913 Handle<Code> CallStubCompiler::CompileCustomCall( | 1928 Handle<Code> CallStubCompiler::CompileCustomCall( |
| 1914 Handle<Object> object, | 1929 Handle<Object> object, |
| 1915 Handle<JSObject> holder, | 1930 Handle<JSObject> holder, |
| 1916 Handle<Cell> cell, | 1931 Handle<Cell> cell, |
| 1917 Handle<JSFunction> function, | 1932 Handle<JSFunction> function, |
| 1918 Handle<String> fname, | 1933 Handle<String> fname, |
| 1919 Code::StubType type) { | 1934 Code::StubType type) { |
| 1920 ASSERT(HasCustomCallGenerator(function)); | 1935 ASSERT(HasCustomCallGenerator(function)); |
| 1921 | 1936 |
| 1922 if (function->shared()->HasBuiltinFunctionId()) { | 1937 if (function->shared()->HasBuiltinFunctionId()) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1972 Initialize(Handle<JSFunction>::null()); | 1987 Initialize(Handle<JSFunction>::null()); |
| 1973 } | 1988 } |
| 1974 } | 1989 } |
| 1975 | 1990 |
| 1976 | 1991 |
| 1977 CallOptimization::CallOptimization(Handle<JSFunction> function) { | 1992 CallOptimization::CallOptimization(Handle<JSFunction> function) { |
| 1978 Initialize(function); | 1993 Initialize(function); |
| 1979 } | 1994 } |
| 1980 | 1995 |
| 1981 | 1996 |
| 1982 int CallOptimization::GetPrototypeDepthOfExpectedType( | 1997 Handle<Map> CallOptimization::LookupHolderOfExpectedType( |
| 1998 Handle<JSObject> receiver, |
| 1983 Handle<JSObject> object, | 1999 Handle<JSObject> object, |
| 1984 Handle<JSObject> holder) const { | 2000 Handle<JSObject> holder, |
| 2001 HolderLookup* holder_lookup) const { |
| 1985 ASSERT(is_simple_api_call()); | 2002 ASSERT(is_simple_api_call()); |
| 1986 if (expected_receiver_type_.is_null()) return 0; | 2003 ASSERT_EQ(kHolderNotFound, *holder_lookup); |
| 1987 int depth = 0; | 2004 *holder_lookup = kHolderIsReceiver; |
| 2005 Handle<Map> map_to_holder; |
| 2006 if (expected_receiver_type_.is_null()) { |
| 2007 // no expected type, load from receiver. |
| 2008 return map_to_holder; |
| 2009 } |
| 2010 // walk down the prototype chain to the object |
| 2011 while (!receiver.is_identical_to(object)) { |
| 2012 *holder_lookup = kHolderIsPrototypeOfMap; |
| 2013 map_to_holder = Handle<Map>(receiver->map()); |
| 2014 receiver = Handle<JSObject>(JSObject::cast(map_to_holder->prototype())); |
| 2015 } |
| 2016 // start looking for the holder |
| 1988 while (!object.is_identical_to(holder)) { | 2017 while (!object.is_identical_to(holder)) { |
| 1989 if (expected_receiver_type_->IsTemplateFor(object->map())) return depth; | 2018 Handle<Map> object_map(object->map()); |
| 1990 object = Handle<JSObject>(JSObject::cast(object->GetPrototype())); | 2019 if (expected_receiver_type_->IsTemplateFor(*object_map)) { |
| 1991 if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth; | 2020 return map_to_holder; |
| 1992 ++depth; | 2021 } |
| 2022 if (!object_map->is_hidden_prototype()) { |
| 2023 *holder_lookup = kHolderNotFound; |
| 2024 return Handle<Map>::null(); |
| 2025 } |
| 2026 *holder_lookup = kHolderIsPrototypeOfMap; |
| 2027 map_to_holder = object_map; |
| 2028 object = Handle<JSObject>(JSObject::cast(object_map->prototype())); |
| 1993 } | 2029 } |
| 1994 if (expected_receiver_type_->IsTemplateFor(holder->map())) return depth; | 2030 if (expected_receiver_type_->IsTemplateFor(holder->map())) { |
| 1995 return kInvalidProtoDepth; | 2031 return map_to_holder; |
| 2032 } |
| 2033 *holder_lookup = kHolderNotFound; |
| 2034 return Handle<Map>::null(); |
| 1996 } | 2035 } |
| 1997 | 2036 |
| 1998 | 2037 |
| 1999 void CallOptimization::Initialize(Handle<JSFunction> function) { | 2038 void CallOptimization::Initialize(Handle<JSFunction> function) { |
| 2000 constant_function_ = Handle<JSFunction>::null(); | 2039 constant_function_ = Handle<JSFunction>::null(); |
| 2001 is_simple_api_call_ = false; | 2040 is_simple_api_call_ = false; |
| 2002 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); | 2041 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); |
| 2003 api_call_info_ = Handle<CallHandlerInfo>::null(); | 2042 api_call_info_ = Handle<CallHandlerInfo>::null(); |
| 2004 | 2043 |
| 2005 if (function.is_null() || !function->is_compiled()) return; | 2044 if (function.is_null() || !function->is_compiled()) return; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2029 Handle<FunctionTemplateInfo>( | 2068 Handle<FunctionTemplateInfo>( |
| 2030 FunctionTemplateInfo::cast(signature->receiver())); | 2069 FunctionTemplateInfo::cast(signature->receiver())); |
| 2031 } | 2070 } |
| 2032 } | 2071 } |
| 2033 | 2072 |
| 2034 is_simple_api_call_ = true; | 2073 is_simple_api_call_ = true; |
| 2035 } | 2074 } |
| 2036 | 2075 |
| 2037 | 2076 |
| 2038 } } // namespace v8::internal | 2077 } } // namespace v8::internal |
| OLD | NEW |