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 |