| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/ic/ic.h" | 5 #include "src/ic/ic.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK); | 552 PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK); |
| 553 } | 553 } |
| 554 | 554 |
| 555 | 555 |
| 556 // static | 556 // static |
| 557 Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate, | 557 Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate, |
| 558 ExtraICState extra_state) { | 558 ExtraICState extra_state) { |
| 559 if (FLAG_compiled_keyed_generic_loads) { | 559 if (FLAG_compiled_keyed_generic_loads) { |
| 560 return KeyedLoadGenericStub(isolate, LoadICState(extra_state)).GetCode(); | 560 return KeyedLoadGenericStub(isolate, LoadICState(extra_state)).GetCode(); |
| 561 } else { | 561 } else { |
| 562 return is_strong(LoadICState::GetLanguageMode(extra_state)) | 562 return isolate->builtins()->KeyedLoadIC_Megamorphic(); |
| 563 ? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong() | |
| 564 : isolate->builtins()->KeyedLoadIC_Megamorphic(); | |
| 565 } | 563 } |
| 566 } | 564 } |
| 567 | 565 |
| 568 | 566 |
| 569 static bool MigrateDeprecated(Handle<Object> object) { | 567 static bool MigrateDeprecated(Handle<Object> object) { |
| 570 if (!object->IsJSObject()) return false; | 568 if (!object->IsJSObject()) return false; |
| 571 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 569 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 572 if (!receiver->map()->is_deprecated()) return false; | 570 if (!receiver->map()->is_deprecated()) return false; |
| 573 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 571 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
| 574 return true; | 572 return true; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 uint32_t index; | 659 uint32_t index; |
| 662 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 660 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 663 // Rewrite to the generic keyed load stub. | 661 // Rewrite to the generic keyed load stub. |
| 664 if (FLAG_use_ic) { | 662 if (FLAG_use_ic) { |
| 665 DCHECK(UseVector()); | 663 DCHECK(UseVector()); |
| 666 ConfigureVectorState(MEGAMORPHIC); | 664 ConfigureVectorState(MEGAMORPHIC); |
| 667 TRACE_IC("LoadIC", name); | 665 TRACE_IC("LoadIC", name); |
| 668 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 666 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
| 669 } | 667 } |
| 670 Handle<Object> result; | 668 Handle<Object> result; |
| 671 ASSIGN_RETURN_ON_EXCEPTION( | 669 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
| 672 isolate(), result, | 670 Object::GetElement(isolate(), object, index), |
| 673 Object::GetElement(isolate(), object, index, language_mode()), Object); | 671 Object); |
| 674 return result; | 672 return result; |
| 675 } | 673 } |
| 676 | 674 |
| 677 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | 675 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
| 678 | 676 |
| 679 if (object->IsJSGlobalObject() && name->IsString()) { | 677 if (object->IsJSGlobalObject() && name->IsString()) { |
| 680 // Look up in script context table. | 678 // Look up in script context table. |
| 681 Handle<String> str_name = Handle<String>::cast(name); | 679 Handle<String> str_name = Handle<String>::cast(name); |
| 682 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object); | 680 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object); |
| 683 Handle<ScriptContextTable> script_contexts( | 681 Handle<ScriptContextTable> script_contexts( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 707 LookupIterator it(object, name); | 705 LookupIterator it(object, name); |
| 708 LookupForRead(&it); | 706 LookupForRead(&it); |
| 709 | 707 |
| 710 if (it.IsFound() || !ShouldThrowReferenceError(object)) { | 708 if (it.IsFound() || !ShouldThrowReferenceError(object)) { |
| 711 // Update inline cache and stub cache. | 709 // Update inline cache and stub cache. |
| 712 if (use_ic) UpdateCaches(&it); | 710 if (use_ic) UpdateCaches(&it); |
| 713 | 711 |
| 714 // Get the property. | 712 // Get the property. |
| 715 Handle<Object> result; | 713 Handle<Object> result; |
| 716 | 714 |
| 717 ASSIGN_RETURN_ON_EXCEPTION( | 715 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it), |
| 718 isolate(), result, Object::GetProperty(&it, language_mode()), Object); | 716 Object); |
| 719 if (it.IsFound()) { | 717 if (it.IsFound()) { |
| 720 return result; | 718 return result; |
| 721 } else if (!ShouldThrowReferenceError(object)) { | 719 } else if (!ShouldThrowReferenceError(object)) { |
| 722 LOG(isolate(), SuspectReadEvent(*name, *object)); | 720 LOG(isolate(), SuspectReadEvent(*name, *object)); |
| 723 return result; | 721 return result; |
| 724 } | 722 } |
| 725 } | 723 } |
| 726 return ReferenceError(name); | 724 return ReferenceError(name); |
| 727 } | 725 } |
| 728 | 726 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 ExtraICState extra_state) { | 891 ExtraICState extra_state) { |
| 894 return KeyedLoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); | 892 return KeyedLoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); |
| 895 } | 893 } |
| 896 | 894 |
| 897 | 895 |
| 898 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( | 896 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( |
| 899 Isolate* isolate, State initialization_state, ExtraICState extra_state) { | 897 Isolate* isolate, State initialization_state, ExtraICState extra_state) { |
| 900 if (initialization_state != MEGAMORPHIC) { | 898 if (initialization_state != MEGAMORPHIC) { |
| 901 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); | 899 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); |
| 902 } | 900 } |
| 903 return is_strong(LoadICState::GetLanguageMode(extra_state)) | 901 return isolate->builtins()->KeyedLoadIC_Megamorphic(); |
| 904 ? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong() | |
| 905 : isolate->builtins()->KeyedLoadIC_Megamorphic(); | |
| 906 } | 902 } |
| 907 | 903 |
| 908 | 904 |
| 909 static Handle<Code> KeyedStoreICInitializeStubHelper( | 905 static Handle<Code> KeyedStoreICInitializeStubHelper( |
| 910 Isolate* isolate, LanguageMode language_mode, | 906 Isolate* isolate, LanguageMode language_mode, |
| 911 InlineCacheState initialization_state) { | 907 InlineCacheState initialization_state) { |
| 912 switch (initialization_state) { | 908 switch (initialization_state) { |
| 913 case UNINITIALIZED: | 909 case UNINITIALIZED: |
| 914 return is_strict(language_mode) | 910 return is_strict(language_mode) |
| 915 ? isolate->builtins()->KeyedStoreIC_Initialize_Strict() | 911 ? isolate->builtins()->KeyedStoreIC_Initialize_Strict() |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 ConfigureVectorState(PREMONOMORPHIC); | 1014 ConfigureVectorState(PREMONOMORPHIC); |
| 1019 TRACE_IC("LoadIC", lookup->name()); | 1015 TRACE_IC("LoadIC", lookup->name()); |
| 1020 return; | 1016 return; |
| 1021 } | 1017 } |
| 1022 | 1018 |
| 1023 Handle<Code> code; | 1019 Handle<Code> code; |
| 1024 if (lookup->state() == LookupIterator::JSPROXY || | 1020 if (lookup->state() == LookupIterator::JSPROXY || |
| 1025 lookup->state() == LookupIterator::ACCESS_CHECK) { | 1021 lookup->state() == LookupIterator::ACCESS_CHECK) { |
| 1026 code = slow_stub(); | 1022 code = slow_stub(); |
| 1027 } else if (!lookup->IsFound()) { | 1023 } else if (!lookup->IsFound()) { |
| 1028 if (kind() == Code::LOAD_IC && !is_strong(language_mode())) { | 1024 if (kind() == Code::LOAD_IC) { |
| 1029 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), | 1025 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), |
| 1030 receiver_map()); | 1026 receiver_map()); |
| 1031 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 1027 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
| 1032 if (code.is_null()) code = slow_stub(); | 1028 if (code.is_null()) code = slow_stub(); |
| 1033 } else { | 1029 } else { |
| 1034 code = slow_stub(); | 1030 code = slow_stub(); |
| 1035 } | 1031 } |
| 1036 } else { | 1032 } else { |
| 1037 if (lookup->state() == LookupIterator::ACCESSOR) { | 1033 if (lookup->state() == LookupIterator::ACCESSOR) { |
| 1038 if (!IsCompatibleReceiver(lookup, receiver_map())) { | 1034 if (!IsCompatibleReceiver(lookup, receiver_map())) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1225 Handle<Map> stub_holder_map = | 1221 Handle<Map> stub_holder_map = |
| 1226 GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag); | 1222 GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag); |
| 1227 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | 1223 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); |
| 1228 return code; | 1224 return code; |
| 1229 } | 1225 } |
| 1230 // There is only one shared stub for loading normalized | 1226 // There is only one shared stub for loading normalized |
| 1231 // properties. It does not traverse the prototype chain, so the | 1227 // properties. It does not traverse the prototype chain, so the |
| 1232 // property must be found in the object for the stub to be | 1228 // property must be found in the object for the stub to be |
| 1233 // applicable. | 1229 // applicable. |
| 1234 if (!receiver_is_holder) break; | 1230 if (!receiver_is_holder) break; |
| 1235 return is_strong(language_mode()) | 1231 return isolate()->builtins()->LoadIC_Normal(); |
| 1236 ? isolate()->builtins()->LoadIC_Normal_Strong() | |
| 1237 : isolate()->builtins()->LoadIC_Normal(); | |
| 1238 } | 1232 } |
| 1239 | 1233 |
| 1240 // -------------- Fields -------------- | 1234 // -------------- Fields -------------- |
| 1241 if (lookup->property_details().type() == DATA) { | 1235 if (lookup->property_details().type() == DATA) { |
| 1242 FieldIndex field = lookup->GetFieldIndex(); | 1236 FieldIndex field = lookup->GetFieldIndex(); |
| 1243 if (receiver_is_holder) { | 1237 if (receiver_is_holder) { |
| 1244 return SimpleFieldLoad(field); | 1238 return SimpleFieldLoad(field); |
| 1245 } | 1239 } |
| 1246 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1240 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1247 return compiler.CompileLoadField(lookup->name(), field); | 1241 return compiler.CompileLoadField(lookup->name(), field); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 | 1331 |
| 1338 // If the maximum number of receiver maps has been exceeded, use the generic | 1332 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1339 // version of the IC. | 1333 // version of the IC. |
| 1340 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1334 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1341 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1335 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
| 1342 return megamorphic_stub(); | 1336 return megamorphic_stub(); |
| 1343 } | 1337 } |
| 1344 | 1338 |
| 1345 CodeHandleList handlers(target_receiver_maps.length()); | 1339 CodeHandleList handlers(target_receiver_maps.length()); |
| 1346 ElementHandlerCompiler compiler(isolate()); | 1340 ElementHandlerCompiler compiler(isolate()); |
| 1347 compiler.CompileElementHandlers(&target_receiver_maps, &handlers, | 1341 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
| 1348 language_mode()); | |
| 1349 ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers); | 1342 ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers); |
| 1350 return null_handle; | 1343 return null_handle; |
| 1351 } | 1344 } |
| 1352 | 1345 |
| 1353 | 1346 |
| 1354 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1347 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
| 1355 Handle<Object> key) { | 1348 Handle<Object> key) { |
| 1356 if (MigrateDeprecated(object)) { | 1349 if (MigrateDeprecated(object)) { |
| 1357 Handle<Object> result; | 1350 Handle<Object> result; |
| 1358 ASSIGN_RETURN_ON_EXCEPTION( | 1351 ASSIGN_RETURN_ON_EXCEPTION( |
| 1359 isolate(), result, | 1352 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), |
| 1360 Runtime::GetObjectProperty(isolate(), object, key, language_mode()), | |
| 1361 Object); | 1353 Object); |
| 1362 return result; | 1354 return result; |
| 1363 } | 1355 } |
| 1364 | 1356 |
| 1365 Handle<Object> load_handle; | 1357 Handle<Object> load_handle; |
| 1366 Handle<Code> stub = megamorphic_stub(); | 1358 Handle<Code> stub = megamorphic_stub(); |
| 1367 | 1359 |
| 1368 // Check for non-string values that can be converted into an | 1360 // Check for non-string values that can be converted into an |
| 1369 // internalized string directly or is representable as a smi. | 1361 // internalized string directly or is representable as a smi. |
| 1370 key = TryConvertKey(key, isolate()); | 1362 key = TryConvertKey(key, isolate()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1388 ConfigureVectorState(MEGAMORPHIC); | 1380 ConfigureVectorState(MEGAMORPHIC); |
| 1389 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1381 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1390 } | 1382 } |
| 1391 | 1383 |
| 1392 TRACE_IC("LoadIC", key); | 1384 TRACE_IC("LoadIC", key); |
| 1393 } | 1385 } |
| 1394 | 1386 |
| 1395 if (!load_handle.is_null()) return load_handle; | 1387 if (!load_handle.is_null()) return load_handle; |
| 1396 | 1388 |
| 1397 Handle<Object> result; | 1389 Handle<Object> result; |
| 1398 ASSIGN_RETURN_ON_EXCEPTION( | 1390 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
| 1399 isolate(), result, | 1391 Runtime::GetObjectProperty(isolate(), object, key), |
| 1400 Runtime::GetObjectProperty(isolate(), object, key, language_mode()), | 1392 Object); |
| 1401 Object); | |
| 1402 return result; | 1393 return result; |
| 1403 } | 1394 } |
| 1404 | 1395 |
| 1405 | 1396 |
| 1406 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value, | 1397 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value, |
| 1407 JSReceiver::StoreFromKeyed store_mode) { | 1398 JSReceiver::StoreFromKeyed store_mode) { |
| 1408 // Disable ICs for non-JSObjects for now. | 1399 // Disable ICs for non-JSObjects for now. |
| 1409 Handle<Object> object = it->GetReceiver(); | 1400 Handle<Object> object = it->GetReceiver(); |
| 1410 if (!object->IsJSObject()) return false; | 1401 if (!object->IsJSObject()) return false; |
| 1411 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1402 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| (...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2912 } | 2903 } |
| 2913 | 2904 |
| 2914 | 2905 |
| 2915 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) { | 2906 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) { |
| 2916 // TODO(verwaest): This should probably get the holder and receiver as input. | 2907 // TODO(verwaest): This should probably get the holder and receiver as input. |
| 2917 HandleScope scope(isolate); | 2908 HandleScope scope(isolate); |
| 2918 Handle<JSObject> receiver = args.at<JSObject>(0); | 2909 Handle<JSObject> receiver = args.at<JSObject>(0); |
| 2919 DCHECK(args.smi_at(1) >= 0); | 2910 DCHECK(args.smi_at(1) >= 0); |
| 2920 uint32_t index = args.smi_at(1); | 2911 uint32_t index = args.smi_at(1); |
| 2921 Handle<Object> result; | 2912 Handle<Object> result; |
| 2922 // TODO(conradw): Investigate strong mode semantics for this. | |
| 2923 LanguageMode language_mode = SLOPPY; | |
| 2924 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2913 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2925 isolate, result, | 2914 isolate, result, Object::GetElement(isolate, receiver, index)); |
| 2926 Object::GetElement(isolate, receiver, index, language_mode)); | |
| 2927 return *result; | 2915 return *result; |
| 2928 } | 2916 } |
| 2929 | 2917 |
| 2930 | 2918 |
| 2931 RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) { | 2919 RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) { |
| 2932 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2920 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2933 HandleScope scope(isolate); | 2921 HandleScope scope(isolate); |
| 2934 Handle<Object> receiver = args.at<Object>(0); | 2922 Handle<Object> receiver = args.at<Object>(0); |
| 2935 Handle<Name> key = args.at<Name>(1); | 2923 Handle<Name> key = args.at<Name>(1); |
| 2936 Handle<Object> result; | 2924 Handle<Object> result; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2953 KeyedLoadICNexus nexus(vector, vector_slot); | 2941 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2954 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2942 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2955 ic.UpdateState(receiver, key); | 2943 ic.UpdateState(receiver, key); |
| 2956 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2944 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2957 } | 2945 } |
| 2958 | 2946 |
| 2959 return *result; | 2947 return *result; |
| 2960 } | 2948 } |
| 2961 } // namespace internal | 2949 } // namespace internal |
| 2962 } // namespace v8 | 2950 } // namespace v8 |
| OLD | NEW |