Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: src/ic.cc

Issue 112863002: Merge bleeding_edge 18021:18297 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 if (raw_frame->is_internal()) { 82 if (raw_frame->is_internal()) {
83 Code* apply_builtin = isolate()->builtins()->builtin( 83 Code* apply_builtin = isolate()->builtins()->builtin(
84 Builtins::kFunctionApply); 84 Builtins::kFunctionApply);
85 if (raw_frame->unchecked_code() == apply_builtin) { 85 if (raw_frame->unchecked_code() == apply_builtin) {
86 PrintF("apply from "); 86 PrintF("apply from ");
87 it.Advance(); 87 it.Advance();
88 raw_frame = it.frame(); 88 raw_frame = it.frame();
89 } 89 }
90 } 90 }
91 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); 91 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
92 Code::ExtraICState extra_state = new_target->extra_ic_state(); 92 ExtraICState extra_state = new_target->extra_ic_state();
93 const char* modifier = 93 const char* modifier =
94 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state)); 94 GetTransitionMarkModifier(
95 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
95 PrintF(" (%c->%c%s)", 96 PrintF(" (%c->%c%s)",
96 TransitionMarkFromState(state()), 97 TransitionMarkFromState(state()),
97 TransitionMarkFromState(new_state), 98 TransitionMarkFromState(new_state),
98 modifier); 99 modifier);
99 name->Print(); 100 name->Print();
100 PrintF("]\n"); 101 PrintF("]\n");
101 } 102 }
102 } 103 }
103 104
104 #define TRACE_GENERIC_IC(isolate, type, reason) \ 105 #define TRACE_GENERIC_IC(isolate, type, reason) \
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 bool was_uninitialized = 433 bool was_uninitialized =
433 old_state == UNINITIALIZED || old_state == PREMONOMORPHIC; 434 old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
434 bool is_uninitialized = 435 bool is_uninitialized =
435 new_state == UNINITIALIZED || new_state == PREMONOMORPHIC; 436 new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
436 return (was_uninitialized && !is_uninitialized) ? 1 : 437 return (was_uninitialized && !is_uninitialized) ? 1 :
437 (!was_uninitialized && is_uninitialized) ? -1 : 0; 438 (!was_uninitialized && is_uninitialized) ? -1 : 0;
438 } 439 }
439 440
440 441
441 void IC::PostPatching(Address address, Code* target, Code* old_target) { 442 void IC::PostPatching(Address address, Code* target, Code* old_target) {
442 if (FLAG_type_info_threshold == 0 && !FLAG_watch_ic_patching) {
443 return;
444 }
445 Isolate* isolate = target->GetHeap()->isolate(); 443 Isolate* isolate = target->GetHeap()->isolate();
446 Code* host = isolate-> 444 Code* host = isolate->
447 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 445 inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
448 if (host->kind() != Code::FUNCTION) return; 446 if (host->kind() != Code::FUNCTION) return;
449 447
450 if (FLAG_type_info_threshold > 0 && 448 if (FLAG_type_info_threshold > 0 &&
451 old_target->is_inline_cache_stub() && 449 old_target->is_inline_cache_stub() &&
452 target->is_inline_cache_stub()) { 450 target->is_inline_cache_stub()) {
453 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), 451 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
454 target->ic_state()); 452 target->ic_state());
455 // Not all Code objects have TypeFeedbackInfo. 453 // Not all Code objects have TypeFeedbackInfo.
456 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { 454 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
457 TypeFeedbackInfo* info = 455 TypeFeedbackInfo* info =
458 TypeFeedbackInfo::cast(host->type_feedback_info()); 456 TypeFeedbackInfo::cast(host->type_feedback_info());
459 info->change_ic_with_type_info_count(delta); 457 info->change_ic_with_type_info_count(delta);
460 } 458 }
461 } 459 }
462 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { 460 if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
463 TypeFeedbackInfo* info = 461 TypeFeedbackInfo* info =
464 TypeFeedbackInfo::cast(host->type_feedback_info()); 462 TypeFeedbackInfo::cast(host->type_feedback_info());
465 info->change_own_type_change_checksum(); 463 info->change_own_type_change_checksum();
466 } 464 }
467 if (FLAG_watch_ic_patching) { 465 host->set_profiler_ticks(0);
468 host->set_profiler_ticks(0); 466 isolate->runtime_profiler()->NotifyICChanged();
469 isolate->runtime_profiler()->NotifyICChanged();
470 }
471 // TODO(2029): When an optimized function is patched, it would 467 // TODO(2029): When an optimized function is patched, it would
472 // be nice to propagate the corresponding type information to its 468 // be nice to propagate the corresponding type information to its
473 // unoptimized version for the benefit of later inlining. 469 // unoptimized version for the benefit of later inlining.
474 } 470 }
475 471
476 472
477 void IC::Clear(Isolate* isolate, Address address) { 473 void IC::Clear(Isolate* isolate, Address address) {
478 Code* target = GetTargetAtAddress(address); 474 Code* target = GetTargetAtAddress(address);
479 475
480 // Don't clear debug break inline cache as it will remove the break point. 476 // Don't clear debug break inline cache as it will remove the break point.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { 521 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) {
526 if (IsCleared(target)) return; 522 if (IsCleared(target)) return;
527 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); 523 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
528 } 524 }
529 525
530 526
531 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { 527 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) {
532 if (IsCleared(target)) return; 528 if (IsCleared(target)) return;
533 SetTargetAtAddress(address, 529 SetTargetAtAddress(address,
534 *pre_monomorphic_stub( 530 *pre_monomorphic_stub(
535 isolate, Code::GetStrictMode(target->extra_ic_state()))); 531 isolate, StoreIC::GetStrictMode(target->extra_ic_state())));
536 } 532 }
537 533
538 534
539 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { 535 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) {
540 if (IsCleared(target)) return; 536 if (IsCleared(target)) return;
541 SetTargetAtAddress(address, 537 SetTargetAtAddress(address,
542 *pre_monomorphic_stub( 538 *pre_monomorphic_stub(
543 isolate, Code::GetStrictMode(target->extra_ic_state()))); 539 isolate, StoreIC::GetStrictMode(target->extra_ic_state())));
544 } 540 }
545 541
546 542
547 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { 543 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) {
548 ASSERT(target->major_key() == CodeStub::CompareIC); 544 ASSERT(target->major_key() == CodeStub::CompareIC);
549 CompareIC::State handler_state; 545 CompareIC::State handler_state;
550 Token::Value op; 546 Token::Value op;
551 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, 547 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
552 &handler_state, &op); 548 &handler_state, &op);
553 // Only clear CompareICs that can retain objects. 549 // Only clear CompareICs that can retain objects.
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 // If there's no appropriate stub we simply avoid updating the caches. 772 // If there's no appropriate stub we simply avoid updating the caches.
777 // TODO(verwaest): Install a slow fallback in this case to avoid not learning, 773 // TODO(verwaest): Install a slow fallback in this case to avoid not learning,
778 // and deopting Crankshaft code. 774 // and deopting Crankshaft code.
779 if (code.is_null()) return; 775 if (code.is_null()) return;
780 776
781 Handle<JSObject> cache_object = object->IsJSObject() 777 Handle<JSObject> cache_object = object->IsJSObject()
782 ? Handle<JSObject>::cast(object) 778 ? Handle<JSObject>::cast(object)
783 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), 779 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
784 isolate()); 780 isolate());
785 781
786 PatchCache(handle(Type::OfCurrently(cache_object), isolate()), name, code); 782 PatchCache(CurrentTypeOf(cache_object, isolate()), name, code);
787 TRACE_IC("CallIC", name); 783 TRACE_IC("CallIC", name);
788 } 784 }
789 785
790 786
791 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, 787 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object,
792 Handle<Object> key) { 788 Handle<Object> key) {
793 if (key->IsInternalizedString()) { 789 if (key->IsInternalizedString()) {
794 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); 790 return CallICBase::LoadFunction(object, Handle<String>::cast(key));
795 } 791 }
796 792
(...skipping 18 matching lines...) Expand all
815 ElementsKind kind = array->map()->elements_kind(); 811 ElementsKind kind = array->map()->elements_kind();
816 if (IsFastObjectElementsKind(kind) && 812 if (IsFastObjectElementsKind(kind) &&
817 array->map() == isolate()->get_initial_js_array_map(kind)) { 813 array->map() == isolate()->get_initial_js_array_map(kind)) {
818 KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc); 814 KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc);
819 stub = stub_gen.GetCode(isolate()); 815 stub = stub_gen.GetCode(isolate());
820 } 816 }
821 } 817 }
822 818
823 if (stub.is_null()) { 819 if (stub.is_null()) {
824 stub = isolate()->stub_cache()->ComputeCallMegamorphic( 820 stub = isolate()->stub_cache()->ComputeCallMegamorphic(
825 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); 821 argc, Code::KEYED_CALL_IC, kNoExtraICState);
826 if (object->IsJSObject()) { 822 if (object->IsJSObject()) {
827 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 823 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
828 if (receiver->elements()->map() == 824 if (receiver->elements()->map() ==
829 isolate()->heap()->non_strict_arguments_elements_map()) { 825 isolate()->heap()->non_strict_arguments_elements_map()) {
830 stub = isolate()->stub_cache()->ComputeCallArguments(argc); 826 stub = isolate()->stub_cache()->ComputeCallArguments(argc);
831 } 827 }
832 } 828 }
833 ASSERT(!stub.is_null()); 829 ASSERT(!stub.is_null());
834 } 830 }
835 set_target(*stub); 831 set_target(*stub);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 stub = pre_monomorphic_stub(); 868 stub = pre_monomorphic_stub();
873 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) { 869 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) {
874 StringLengthStub string_length_stub(kind()); 870 StringLengthStub string_length_stub(kind());
875 stub = string_length_stub.GetCode(isolate()); 871 stub = string_length_stub.GetCode(isolate());
876 } else if (state() != MEGAMORPHIC) { 872 } else if (state() != MEGAMORPHIC) {
877 ASSERT(state() != GENERIC); 873 ASSERT(state() != GENERIC);
878 stub = megamorphic_stub(); 874 stub = megamorphic_stub();
879 } 875 }
880 if (!stub.is_null()) { 876 if (!stub.is_null()) {
881 set_target(*stub); 877 set_target(*stub);
882 #ifdef DEBUG
883 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); 878 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n");
884 #endif
885 } 879 }
886 // Get the string if we have a string wrapper object. 880 // Get the string if we have a string wrapper object.
887 String* string = String::cast(JSValue::cast(*object)->value()); 881 String* string = String::cast(JSValue::cast(*object)->value());
888 return Smi::FromInt(string->length()); 882 return Smi::FromInt(string->length());
889 } 883 }
890 884
891 // Use specialized code for getting prototype of functions. 885 // Use specialized code for getting prototype of functions.
892 if (object->IsJSFunction() && 886 if (object->IsJSFunction() &&
893 name->Equals(isolate()->heap()->prototype_string()) && 887 name->Equals(isolate()->heap()->prototype_string()) &&
894 Handle<JSFunction>::cast(object)->should_have_prototype()) { 888 Handle<JSFunction>::cast(object)->should_have_prototype()) {
895 Handle<Code> stub; 889 Handle<Code> stub;
896 if (state() == UNINITIALIZED) { 890 if (state() == UNINITIALIZED) {
897 stub = pre_monomorphic_stub(); 891 stub = pre_monomorphic_stub();
898 } else if (state() == PREMONOMORPHIC) { 892 } else if (state() == PREMONOMORPHIC) {
899 FunctionPrototypeStub function_prototype_stub(kind()); 893 FunctionPrototypeStub function_prototype_stub(kind());
900 stub = function_prototype_stub.GetCode(isolate()); 894 stub = function_prototype_stub.GetCode(isolate());
901 } else if (state() != MEGAMORPHIC) { 895 } else if (state() != MEGAMORPHIC) {
902 ASSERT(state() != GENERIC); 896 ASSERT(state() != GENERIC);
903 stub = megamorphic_stub(); 897 stub = megamorphic_stub();
904 } 898 }
905 if (!stub.is_null()) { 899 if (!stub.is_null()) {
906 set_target(*stub); 900 set_target(*stub);
907 #ifdef DEBUG
908 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); 901 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
909 #endif
910 } 902 }
911 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); 903 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object));
912 } 904 }
913 } 905 }
914 906
915 // Check if the name is trivially convertible to an index and get 907 // Check if the name is trivially convertible to an index and get
916 // the element or char if so. 908 // the element or char if so.
917 uint32_t index; 909 uint32_t index;
918 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { 910 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
919 // Rewrite to the generic keyed load stub. 911 // Rewrite to the generic keyed load stub.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 number_of_valid_types = number_of_types; 974 number_of_valid_types = number_of_types;
983 975
984 for (int i = 0; i < number_of_types; i++) { 976 for (int i = 0; i < number_of_types; i++) {
985 Handle<Type> current_type = types.at(i); 977 Handle<Type> current_type = types.at(i);
986 // Filter out deprecated maps to ensure their instances get migrated. 978 // Filter out deprecated maps to ensure their instances get migrated.
987 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { 979 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
988 number_of_valid_types--; 980 number_of_valid_types--;
989 // If the receiver type is already in the polymorphic IC, this indicates 981 // If the receiver type is already in the polymorphic IC, this indicates
990 // there was a prototoype chain failure. In that case, just overwrite the 982 // there was a prototoype chain failure. In that case, just overwrite the
991 // handler. 983 // handler.
992 } else if (type->Is(current_type)) { 984 } else if (type->IsCurrently(current_type)) {
993 ASSERT(handler_to_overwrite == -1); 985 ASSERT(handler_to_overwrite == -1);
994 number_of_valid_types--; 986 number_of_valid_types--;
995 handler_to_overwrite = i; 987 handler_to_overwrite = i;
996 } 988 }
997 } 989 }
998 990
999 if (number_of_valid_types >= 4) return false; 991 if (number_of_valid_types >= 4) return false;
1000 if (number_of_types == 0) return false; 992 if (number_of_types == 0) return false;
1001 if (!target()->FindHandlers(&handlers, types.length())) return false; 993 if (!target()->FindHandlers(&handlers, types.length())) return false;
1002 994
1003 number_of_valid_types++; 995 number_of_valid_types++;
1004 if (handler_to_overwrite >= 0) { 996 if (handler_to_overwrite >= 0) {
1005 handlers.Set(handler_to_overwrite, code); 997 handlers.Set(handler_to_overwrite, code);
1006 } else { 998 } else {
1007 types.Add(type); 999 types.Add(type);
1008 handlers.Add(code); 1000 handlers.Add(code);
1009 } 1001 }
1010 1002
1011 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( 1003 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
1012 &types, &handlers, number_of_valid_types, name, strict_mode()); 1004 &types, &handlers, number_of_valid_types, name, extra_ic_state());
1013 set_target(*ic); 1005 set_target(*ic);
1014 return true; 1006 return true;
1015 } 1007 }
1016 1008
1017 1009
1010 Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) {
1011 Type* type = object->IsJSGlobalObject()
1012 ? Type::Constant(Handle<JSGlobalObject>::cast(object))
1013 : Type::OfCurrently(object);
1014 return handle(type, isolate);
1015 }
1016
1017
1018 Handle<Map> IC::TypeToMap(Type* type, Isolate* isolate) { 1018 Handle<Map> IC::TypeToMap(Type* type, Isolate* isolate) {
1019 if (type->Is(Type::Number())) return isolate->factory()->heap_number_map(); 1019 if (type->Is(Type::Number())) return isolate->factory()->heap_number_map();
1020 if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map(); 1020 if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map();
1021 if (type->IsConstant()) {
1022 return handle(Handle<JSGlobalObject>::cast(type->AsConstant())->map());
1023 }
1021 ASSERT(type->IsClass()); 1024 ASSERT(type->IsClass());
1022 return type->AsClass(); 1025 return type->AsClass();
1023 } 1026 }
1024 1027
1025 1028
1026 Type* IC::MapToType(Handle<Map> map) { 1029 Type* IC::MapToType(Handle<Map> map) {
1027 if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(); 1030 if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number();
1028 // The only oddballs that can be recorded in ICs are booleans. 1031 // The only oddballs that can be recorded in ICs are booleans.
1029 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(); 1032 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean();
1030 return Type::Class(map); 1033 return Type::Class(map);
1031 } 1034 }
1032 1035
1033 1036
1034 void IC::UpdateMonomorphicIC(Handle<Type> type, 1037 void IC::UpdateMonomorphicIC(Handle<Type> type,
1035 Handle<Code> handler, 1038 Handle<Code> handler,
1036 Handle<String> name) { 1039 Handle<String> name) {
1037 if (!handler->is_handler()) return set_target(*handler); 1040 if (!handler->is_handler()) return set_target(*handler);
1038 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( 1041 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
1039 name, type, handler, strict_mode()); 1042 name, type, handler, extra_ic_state());
1040 set_target(*ic); 1043 set_target(*ic);
1041 } 1044 }
1042 1045
1043 1046
1044 void IC::CopyICToMegamorphicCache(Handle<String> name) { 1047 void IC::CopyICToMegamorphicCache(Handle<String> name) {
1045 TypeHandleList types; 1048 TypeHandleList types;
1046 CodeHandleList handlers; 1049 CodeHandleList handlers;
1047 target()->FindAllTypes(&types); 1050 target()->FindAllTypes(&types);
1048 if (!target()->FindHandlers(&handlers, types.length())) return; 1051 if (!target()->FindHandlers(&handlers, types.length())) return;
1049 for (int i = 0; i < types.length(); i++) { 1052 for (int i = 0; i < types.length(); i++) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 Handle<String> name) { 1130 Handle<String> name) {
1128 if (state() == UNINITIALIZED) { 1131 if (state() == UNINITIALIZED) {
1129 // This is the first time we execute this inline cache. 1132 // This is the first time we execute this inline cache.
1130 // Set the target to the pre monomorphic stub to delay 1133 // Set the target to the pre monomorphic stub to delay
1131 // setting the monomorphic state. 1134 // setting the monomorphic state.
1132 set_target(*pre_monomorphic_stub()); 1135 set_target(*pre_monomorphic_stub());
1133 TRACE_IC("LoadIC", name); 1136 TRACE_IC("LoadIC", name);
1134 return; 1137 return;
1135 } 1138 }
1136 1139
1140 Handle<Type> type = CurrentTypeOf(object, isolate());
1137 Handle<Code> code; 1141 Handle<Code> code;
1138 if (!lookup->IsCacheable()) { 1142 if (!lookup->IsCacheable()) {
1139 // Bail out if the result is not cacheable. 1143 // Bail out if the result is not cacheable.
1140 code = slow_stub(); 1144 code = slow_stub();
1141 } else if (!lookup->IsProperty()) { 1145 } else if (!lookup->IsProperty()) {
1142 if (kind() == Code::LOAD_IC) { 1146 if (kind() == Code::LOAD_IC) {
1143 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object); 1147 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, type);
1144 } else { 1148 } else {
1145 code = slow_stub(); 1149 code = slow_stub();
1146 } 1150 }
1147 } else { 1151 } else {
1148 code = ComputeHandler(lookup, object, name); 1152 code = ComputeHandler(lookup, object, name);
1149 } 1153 }
1150 1154
1151 PatchCache(handle(Type::OfCurrently(object), isolate()), name, code); 1155 PatchCache(type, name, code);
1152 TRACE_IC("LoadIC", name); 1156 TRACE_IC("LoadIC", name);
1153 } 1157 }
1154 1158
1155 1159
1156 void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) { 1160 void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) {
1157 // Cache code holding map should be consistent with 1161 // Cache code holding map should be consistent with
1158 // GenerateMonomorphicCacheProbe. 1162 // GenerateMonomorphicCacheProbe.
1159 Map* map = *TypeToMap(type, isolate()); 1163 Map* map = *TypeToMap(type, isolate());
1160 isolate()->stub_cache()->Set(name, map, code); 1164 isolate()->stub_cache()->Set(name, map, code);
1161 } 1165 }
1162 1166
1163 1167
1164 Handle<Code> IC::ComputeHandler(LookupResult* lookup, 1168 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1165 Handle<Object> object, 1169 Handle<Object> object,
1166 Handle<String> name, 1170 Handle<String> name,
1167 Handle<Object> value) { 1171 Handle<Object> value) {
1168 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); 1172 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object);
1169 Handle<HeapObject> stub_holder(GetCodeCacheHolder( 1173 Handle<HeapObject> stub_holder(GetCodeCacheHolder(
1170 isolate(), *object, cache_holder)); 1174 isolate(), *object, cache_holder));
1171 1175
1172 Handle<Code> code = isolate()->stub_cache()->FindHandler( 1176 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1173 name, stub_holder, kind(), cache_holder, strict_mode()); 1177 name, handle(stub_holder->map()), kind(), cache_holder);
1174 if (!code.is_null()) return code; 1178 if (!code.is_null()) return code;
1175 1179
1176 code = CompileHandler(lookup, object, name, value, cache_holder); 1180 code = CompileHandler(lookup, object, name, value, cache_holder);
1177 ASSERT(code->is_handler()); 1181 ASSERT(code->is_handler());
1178 1182
1179 if (code->type() != Code::NORMAL) { 1183 if (code->type() != Code::NORMAL) {
1180 HeapObject::UpdateMapCodeCache(stub_holder, name, code); 1184 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
1181 } 1185 }
1182 1186
1183 return code; 1187 return code;
1184 } 1188 }
1185 1189
1186 1190
1187 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, 1191 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1188 Handle<Object> object, 1192 Handle<Object> object,
1189 Handle<String> name, 1193 Handle<String> name,
1190 Handle<Object> unused, 1194 Handle<Object> unused,
1191 InlineCacheHolderFlag cache_holder) { 1195 InlineCacheHolderFlag cache_holder) {
1192 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { 1196 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
1193 int length_index = String::kLengthOffset / kPointerSize; 1197 int length_index = String::kLengthOffset / kPointerSize;
1194 return SimpleFieldLoad(length_index); 1198 return SimpleFieldLoad(length_index);
1195 } 1199 }
1196 1200
1201 Handle<Type> type = CurrentTypeOf(object, isolate());
1197 Handle<JSObject> holder(lookup->holder()); 1202 Handle<JSObject> holder(lookup->holder());
1198 LoadStubCompiler compiler(isolate(), cache_holder, kind()); 1203 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind());
1199 1204
1200 switch (lookup->type()) { 1205 switch (lookup->type()) {
1201 case FIELD: { 1206 case FIELD: {
1202 PropertyIndex field = lookup->GetFieldIndex(); 1207 PropertyIndex field = lookup->GetFieldIndex();
1203 if (object.is_identical_to(holder)) { 1208 if (object.is_identical_to(holder)) {
1204 return SimpleFieldLoad(field.translate(holder), 1209 return SimpleFieldLoad(field.translate(holder),
1205 field.is_inobject(holder), 1210 field.is_inobject(holder),
1206 lookup->representation()); 1211 lookup->representation());
1207 } 1212 }
1208 return compiler.CompileLoadField( 1213 return compiler.CompileLoadField(
1209 object, holder, name, field, lookup->representation()); 1214 type, holder, name, field, lookup->representation());
1210 } 1215 }
1211 case CONSTANT: { 1216 case CONSTANT: {
1212 Handle<Object> constant(lookup->GetConstant(), isolate()); 1217 Handle<Object> constant(lookup->GetConstant(), isolate());
1213 // TODO(2803): Don't compute a stub for cons strings because they cannot 1218 // TODO(2803): Don't compute a stub for cons strings because they cannot
1214 // be embedded into code. 1219 // be embedded into code.
1215 if (constant->IsConsString()) break; 1220 if (constant->IsConsString()) break;
1216 return compiler.CompileLoadConstant(object, holder, name, constant); 1221 return compiler.CompileLoadConstant(type, holder, name, constant);
1217 } 1222 }
1218 case NORMAL: 1223 case NORMAL:
1219 if (kind() != Code::LOAD_IC) break; 1224 if (kind() != Code::LOAD_IC) break;
1220 if (holder->IsGlobalObject()) { 1225 if (holder->IsGlobalObject()) {
1221 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 1226 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1222 Handle<PropertyCell> cell( 1227 Handle<PropertyCell> cell(
1223 global->GetPropertyCell(lookup), isolate()); 1228 global->GetPropertyCell(lookup), isolate());
1224 Handle<Code> code = compiler.CompileLoadGlobal( 1229 Handle<Code> code = compiler.CompileLoadGlobal(
1225 object, global, cell, name, lookup->IsDontDelete()); 1230 type, global, cell, name, lookup->IsDontDelete());
1226 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1231 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1227 Handle<HeapObject> stub_holder(GetCodeCacheHolder( 1232 Handle<HeapObject> stub_holder(GetCodeCacheHolder(
1228 isolate(), *object, cache_holder)); 1233 isolate(), *object, cache_holder));
1229 HeapObject::UpdateMapCodeCache(stub_holder, name, code); 1234 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
1230 return code; 1235 return code;
1231 } 1236 }
1232 // There is only one shared stub for loading normalized 1237 // There is only one shared stub for loading normalized
1233 // properties. It does not traverse the prototype chain, so the 1238 // properties. It does not traverse the prototype chain, so the
1234 // property must be found in the object for the stub to be 1239 // property must be found in the object for the stub to be
1235 // applicable. 1240 // applicable.
1236 if (!object.is_identical_to(holder)) break; 1241 if (!object.is_identical_to(holder)) break;
1237 return isolate()->builtins()->LoadIC_Normal(); 1242 return isolate()->builtins()->LoadIC_Normal();
1238 case CALLBACKS: { 1243 case CALLBACKS: {
1239 // Use simple field loads for some well-known callback properties. 1244 // Use simple field loads for some well-known callback properties.
1240 if (object->IsJSObject()) { 1245 if (object->IsJSObject()) {
1241 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1246 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1242 Handle<Map> map(receiver->map()); 1247 Handle<Map> map(receiver->map());
1243 int object_offset; 1248 int object_offset;
1244 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { 1249 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
1245 return SimpleFieldLoad(object_offset / kPointerSize); 1250 return SimpleFieldLoad(object_offset / kPointerSize);
1246 } 1251 }
1247 } 1252 }
1248 1253
1249 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1254 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1250 if (callback->IsExecutableAccessorInfo()) { 1255 if (callback->IsExecutableAccessorInfo()) {
1251 Handle<ExecutableAccessorInfo> info = 1256 Handle<ExecutableAccessorInfo> info =
1252 Handle<ExecutableAccessorInfo>::cast(callback); 1257 Handle<ExecutableAccessorInfo>::cast(callback);
1253 if (v8::ToCData<Address>(info->getter()) == 0) break; 1258 if (v8::ToCData<Address>(info->getter()) == 0) break;
1254 if (!info->IsCompatibleReceiver(*object)) break; 1259 if (!info->IsCompatibleReceiver(*object)) break;
1255 return compiler.CompileLoadCallback(object, holder, name, info); 1260 return compiler.CompileLoadCallback(type, holder, name, info);
1256 } else if (callback->IsAccessorPair()) { 1261 } else if (callback->IsAccessorPair()) {
1257 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), 1262 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1258 isolate()); 1263 isolate());
1259 if (!getter->IsJSFunction()) break; 1264 if (!getter->IsJSFunction()) break;
1260 if (holder->IsGlobalObject()) break; 1265 if (holder->IsGlobalObject()) break;
1261 if (!holder->HasFastProperties()) break; 1266 if (!holder->HasFastProperties()) break;
1262 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); 1267 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1263 if (!object->IsJSObject() && 1268 if (!object->IsJSObject() &&
1264 !function->IsBuiltin() && 1269 !function->IsBuiltin() &&
1265 function->shared()->is_classic_mode()) { 1270 function->shared()->is_classic_mode()) {
1266 // Calling non-strict non-builtins with a value as the receiver 1271 // Calling non-strict non-builtins with a value as the receiver
1267 // requires boxing. 1272 // requires boxing.
1268 break; 1273 break;
1269 } 1274 }
1270 CallOptimization call_optimization(function); 1275 CallOptimization call_optimization(function);
1271 if (call_optimization.is_simple_api_call() && 1276 if (call_optimization.is_simple_api_call() &&
1272 call_optimization.IsCompatibleReceiver(*object)) { 1277 call_optimization.IsCompatibleReceiver(*object)) {
1273 return compiler.CompileLoadCallback( 1278 return compiler.CompileLoadCallback(
1274 object, holder, name, call_optimization); 1279 type, holder, name, call_optimization);
1275 } 1280 }
1276 return compiler.CompileLoadViaGetter(object, holder, name, function); 1281 return compiler.CompileLoadViaGetter(type, holder, name, function);
1277 } 1282 }
1278 // TODO(dcarney): Handle correctly. 1283 // TODO(dcarney): Handle correctly.
1279 if (callback->IsDeclaredAccessorInfo()) break; 1284 if (callback->IsDeclaredAccessorInfo()) break;
1280 ASSERT(callback->IsForeign()); 1285 ASSERT(callback->IsForeign());
1281 // No IC support for old-style native accessors. 1286 // No IC support for old-style native accessors.
1282 break; 1287 break;
1283 } 1288 }
1284 case INTERCEPTOR: 1289 case INTERCEPTOR:
1285 ASSERT(HasInterceptorGetter(*holder)); 1290 ASSERT(HasInterceptorGetter(*holder));
1286 return compiler.CompileLoadInterceptor(object, holder, name); 1291 return compiler.CompileLoadInterceptor(type, holder, name);
1287 default: 1292 default:
1288 break; 1293 break;
1289 } 1294 }
1290 1295
1291 return slow_stub(); 1296 return slow_stub();
1292 } 1297 }
1293 1298
1294 1299
1295 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { 1300 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1296 // This helper implements a few common fast cases for converting 1301 // This helper implements a few common fast cases for converting
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 receiver->LocalLookupRealNamedProperty(*name, lookup); 1442 receiver->LocalLookupRealNamedProperty(*name, lookup);
1438 return lookup->IsFound() && 1443 return lookup->IsFound() &&
1439 !lookup->IsReadOnly() && 1444 !lookup->IsReadOnly() &&
1440 lookup->CanHoldValue(value) && 1445 lookup->CanHoldValue(value) &&
1441 lookup->IsCacheable(); 1446 lookup->IsCacheable();
1442 } 1447 }
1443 return lookup->CanHoldValue(value); 1448 return lookup->CanHoldValue(value);
1444 } 1449 }
1445 1450
1446 if (lookup->IsPropertyCallbacks()) return true; 1451 if (lookup->IsPropertyCallbacks()) return true;
1447 1452 // JSGlobalProxy always goes via the runtime, so it's safe to cache.
1453 if (receiver->IsJSGlobalProxy()) return true;
1448 // Currently normal holders in the prototype chain are not supported. They 1454 // Currently normal holders in the prototype chain are not supported. They
1449 // would require a runtime positive lookup and verification that the details 1455 // would require a runtime positive lookup and verification that the details
1450 // have not changed. 1456 // have not changed.
1451 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; 1457 if (lookup->IsInterceptor() || lookup->IsNormal()) return false;
1452 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); 1458 holder = Handle<JSObject>(lookup->holder(), lookup->isolate());
1453 } 1459 }
1454 1460
1455 // While normally LookupTransition gets passed the receiver, in this case we 1461 // While normally LookupTransition gets passed the receiver, in this case we
1456 // pass the holder of the property that we overwrite. This keeps the holder in 1462 // pass the holder of the property that we overwrite. This keeps the holder in
1457 // the LookupResult intact so we can later use it to generate a prototype 1463 // the LookupResult intact so we can later use it to generate a prototype
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 Handle<Code> stub = 1550 Handle<Code> stub =
1545 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); 1551 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate());
1546 set_target(*stub); 1552 set_target(*stub);
1547 TRACE_IC("StoreIC", name); 1553 TRACE_IC("StoreIC", name);
1548 Handle<Object> result = JSReceiver::SetProperty( 1554 Handle<Object> result = JSReceiver::SetProperty(
1549 receiver, name, value, NONE, strict_mode(), store_mode); 1555 receiver, name, value, NONE, strict_mode(), store_mode);
1550 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1556 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1551 return *result; 1557 return *result;
1552 } 1558 }
1553 1559
1554 if (receiver->IsJSGlobalProxy()) {
1555 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) {
1556 // Generate a generic stub that goes to the runtime when we see a global
1557 // proxy as receiver.
1558 Handle<Code> stub = global_proxy_stub();
1559 set_target(*stub);
1560 TRACE_IC("StoreIC", name);
1561 }
1562 Handle<Object> result = JSReceiver::SetProperty(
1563 receiver, name, value, NONE, strict_mode(), store_mode);
1564 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1565 return *result;
1566 }
1567
1568 LookupResult lookup(isolate()); 1560 LookupResult lookup(isolate());
1569 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); 1561 bool can_store = LookupForWrite(receiver, name, value, &lookup, this);
1570 if (!can_store && 1562 if (!can_store &&
1571 strict_mode() == kStrictMode && 1563 strict_mode() == kStrictMode &&
1572 !(lookup.IsProperty() && lookup.IsReadOnly()) && 1564 !(lookup.IsProperty() && lookup.IsReadOnly()) &&
1573 IsUndeclaredGlobal(object)) { 1565 IsUndeclaredGlobal(object)) {
1574 // Strict mode doesn't allow setting non-existent global property. 1566 // Strict mode doesn't allow setting non-existent global property.
1575 return ReferenceError("not_defined", name); 1567 return ReferenceError("not_defined", name);
1576 } 1568 }
1577 if (FLAG_use_ic) { 1569 if (FLAG_use_ic) {
(...skipping 16 matching lines...) Expand all
1594 receiver, name, value, NONE, strict_mode(), store_mode); 1586 receiver, name, value, NONE, strict_mode(), store_mode);
1595 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1587 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1596 return *result; 1588 return *result;
1597 } 1589 }
1598 1590
1599 1591
1600 void StoreIC::UpdateCaches(LookupResult* lookup, 1592 void StoreIC::UpdateCaches(LookupResult* lookup,
1601 Handle<JSObject> receiver, 1593 Handle<JSObject> receiver,
1602 Handle<String> name, 1594 Handle<String> name,
1603 Handle<Object> value) { 1595 Handle<Object> value) {
1604 ASSERT(!receiver->IsJSGlobalProxy());
1605 ASSERT(lookup->IsFound()); 1596 ASSERT(lookup->IsFound());
1606 1597
1607 // These are not cacheable, so we never see such LookupResults here. 1598 // These are not cacheable, so we never see such LookupResults here.
1608 ASSERT(!lookup->IsHandler()); 1599 ASSERT(!lookup->IsHandler());
1609 1600
1610 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); 1601 Handle<Code> code = ComputeHandler(lookup, receiver, name, value);
1611 1602
1612 PatchCache(handle(Type::OfCurrently(receiver), isolate()), name, code); 1603 PatchCache(CurrentTypeOf(receiver, isolate()), name, code);
1613 TRACE_IC("StoreIC", name); 1604 TRACE_IC("StoreIC", name);
1614 } 1605 }
1615 1606
1616 1607
1617 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, 1608 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
1618 Handle<Object> object, 1609 Handle<Object> object,
1619 Handle<String> name, 1610 Handle<String> name,
1620 Handle<Object> value, 1611 Handle<Object> value,
1621 InlineCacheHolderFlag cache_holder) { 1612 InlineCacheHolderFlag cache_holder) {
1613 if (object->IsJSGlobalProxy()) return slow_stub();
1622 ASSERT(cache_holder == OWN_MAP); 1614 ASSERT(cache_holder == OWN_MAP);
1623 // This is currently guaranteed by checks in StoreIC::Store. 1615 // This is currently guaranteed by checks in StoreIC::Store.
1624 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1616 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1625 1617
1626 Handle<JSObject> holder(lookup->holder()); 1618 Handle<JSObject> holder(lookup->holder());
1627 StoreStubCompiler compiler(isolate(), strict_mode(), kind()); 1619 // Handlers do not use strict mode.
1620 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind());
1628 switch (lookup->type()) { 1621 switch (lookup->type()) {
1629 case FIELD: 1622 case FIELD:
1630 return compiler.CompileStoreField(receiver, lookup, name); 1623 return compiler.CompileStoreField(receiver, lookup, name);
1631 case TRANSITION: { 1624 case TRANSITION: {
1632 // Explicitly pass in the receiver map since LookupForWrite may have 1625 // Explicitly pass in the receiver map since LookupForWrite may have
1633 // stored something else than the receiver in the holder. 1626 // stored something else than the receiver in the holder.
1634 Handle<Map> transition( 1627 Handle<Map> transition(
1635 lookup->GetTransitionTarget(receiver->map()), isolate()); 1628 lookup->GetTransitionTarget(receiver->map()), isolate());
1636 int descriptor = transition->LastAdded(); 1629 int descriptor = transition->LastAdded();
1637 1630
1638 DescriptorArray* target_descriptors = transition->instance_descriptors(); 1631 DescriptorArray* target_descriptors = transition->instance_descriptors();
1639 PropertyDetails details = target_descriptors->GetDetails(descriptor); 1632 PropertyDetails details = target_descriptors->GetDetails(descriptor);
1640 1633
1641 if (details.type() == CALLBACKS || details.attributes() != NONE) break; 1634 if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1642 1635
1643 return compiler.CompileStoreTransition( 1636 return compiler.CompileStoreTransition(
1644 receiver, lookup, transition, name); 1637 receiver, lookup, transition, name);
1645 } 1638 }
1646 case NORMAL: 1639 case NORMAL:
1647 if (kind() == Code::KEYED_STORE_IC) break; 1640 if (kind() == Code::KEYED_STORE_IC) break;
1648 if (receiver->IsGlobalObject()) { 1641 if (receiver->IsGlobalObject()) {
1649 // The stub generated for the global object picks the value directly 1642 // The stub generated for the global object picks the value directly
1650 // from the property cell. So the property must be directly on the 1643 // from the property cell. So the property must be directly on the
1651 // global object. 1644 // global object.
1652 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1645 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1653 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); 1646 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate());
1654 Handle<Type> union_type = PropertyCell::UpdatedType(cell, value); 1647 Handle<Type> union_type = PropertyCell::UpdatedType(cell, value);
1655 StoreGlobalStub stub(strict_mode(), union_type->IsConstant()); 1648 StoreGlobalStub stub(union_type->IsConstant());
1656 1649
1657 Handle<Code> code = stub.GetCodeCopyFromTemplate( 1650 Handle<Code> code = stub.GetCodeCopyFromTemplate(
1658 isolate(), receiver->map(), *cell); 1651 isolate(), receiver->map(), *cell);
1659 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1652 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1660 HeapObject::UpdateMapCodeCache(receiver, name, code); 1653 HeapObject::UpdateMapCodeCache(receiver, name, code);
1661 return code; 1654 return code;
1662 } 1655 }
1663 ASSERT(holder.is_identical_to(receiver)); 1656 ASSERT(holder.is_identical_to(receiver));
1664 return strict_mode() == kStrictMode 1657 return isolate()->builtins()->StoreIC_Normal();
1665 ? isolate()->builtins()->StoreIC_Normal_Strict()
1666 : isolate()->builtins()->StoreIC_Normal();
1667 case CALLBACKS: { 1658 case CALLBACKS: {
1668 if (kind() == Code::KEYED_STORE_IC) break; 1659 if (kind() == Code::KEYED_STORE_IC) break;
1669 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1660 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1670 if (callback->IsExecutableAccessorInfo()) { 1661 if (callback->IsExecutableAccessorInfo()) {
1671 Handle<ExecutableAccessorInfo> info = 1662 Handle<ExecutableAccessorInfo> info =
1672 Handle<ExecutableAccessorInfo>::cast(callback); 1663 Handle<ExecutableAccessorInfo>::cast(callback);
1673 if (v8::ToCData<Address>(info->setter()) == 0) break; 1664 if (v8::ToCData<Address>(info->setter()) == 0) break;
1674 if (!holder->HasFastProperties()) break; 1665 if (!holder->HasFastProperties()) break;
1675 if (!info->IsCompatibleReceiver(*receiver)) break; 1666 if (!info->IsCompatibleReceiver(*receiver)) break;
1676 return compiler.CompileStoreCallback(receiver, holder, name, info); 1667 return compiler.CompileStoreCallback(receiver, holder, name, info);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 // stores into properties in dictionary mode), then there will be not 1729 // stores into properties in dictionary mode), then there will be not
1739 // receiver maps in the target. 1730 // receiver maps in the target.
1740 return generic_stub(); 1731 return generic_stub();
1741 } 1732 }
1742 1733
1743 // There are several special cases where an IC that is MONOMORPHIC can still 1734 // There are several special cases where an IC that is MONOMORPHIC can still
1744 // transition to a different GetNonTransitioningStoreMode IC that handles a 1735 // transition to a different GetNonTransitioningStoreMode IC that handles a
1745 // superset of the original IC. Handle those here if the receiver map hasn't 1736 // superset of the original IC. Handle those here if the receiver map hasn't
1746 // changed or it has transitioned to a more general kind. 1737 // changed or it has transitioned to a more general kind.
1747 KeyedAccessStoreMode old_store_mode = 1738 KeyedAccessStoreMode old_store_mode =
1748 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); 1739 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
1749 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); 1740 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1750 if (state() == MONOMORPHIC) { 1741 if (state() == MONOMORPHIC) {
1751 // If the "old" and "new" maps are in the same elements map family, stay 1742 // If the "old" and "new" maps are in the same elements map family, stay
1752 // MONOMORPHIC and use the map for the most generic ElementsKind. 1743 // MONOMORPHIC and use the map for the most generic ElementsKind.
1753 Handle<Map> transitioned_receiver_map = receiver_map; 1744 Handle<Map> transitioned_receiver_map = receiver_map;
1754 if (IsTransitionStoreMode(store_mode)) { 1745 if (IsTransitionStoreMode(store_mode)) {
1755 transitioned_receiver_map = 1746 transitioned_receiver_map =
1756 ComputeTransitionedMap(receiver, store_mode); 1747 ComputeTransitionedMap(receiver, store_mode);
1757 } 1748 }
1758 if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) { 1749 if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) {
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after
2314 } 2305 }
2315 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, 2306 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
2316 value, 2307 value,
2317 NONE, 2308 NONE,
2318 strict_mode); 2309 strict_mode);
2319 RETURN_IF_EMPTY_HANDLE(isolate, result); 2310 RETURN_IF_EMPTY_HANDLE(isolate, result);
2320 return *result; 2311 return *result;
2321 } 2312 }
2322 2313
2323 2314
2324 const char* BinaryOpIC::GetName(TypeInfo type_info) { 2315 BinaryOpIC::State::State(ExtraICState extra_ic_state) {
2325 switch (type_info) { 2316 // We don't deserialize the SSE2 Field, since this is only used to be able
2326 case UNINITIALIZED: return "Uninitialized"; 2317 // to include SSE2 as well as non-SSE2 versions in the snapshot. For code
2318 // generation we always want it to reflect the current state.
2319 op_ = static_cast<Token::Value>(
2320 FIRST_TOKEN + OpField::decode(extra_ic_state));
2321 mode_ = OverwriteModeField::decode(extra_ic_state);
2322 fixed_right_arg_ = Maybe<int>(
2323 HasFixedRightArgField::decode(extra_ic_state),
2324 1 << FixedRightArgValueField::decode(extra_ic_state));
2325 left_kind_ = LeftKindField::decode(extra_ic_state);
2326 if (fixed_right_arg_.has_value) {
2327 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32;
2328 } else {
2329 right_kind_ = RightKindField::decode(extra_ic_state);
2330 }
2331 result_kind_ = ResultKindField::decode(extra_ic_state);
2332 ASSERT_LE(FIRST_TOKEN, op_);
2333 ASSERT_LE(op_, LAST_TOKEN);
2334 }
2335
2336
2337 ExtraICState BinaryOpIC::State::GetExtraICState() const {
2338 bool sse2 = (Max(result_kind_, Max(left_kind_, right_kind_)) > SMI &&
2339 CpuFeatures::IsSafeForSnapshot(SSE2));
2340 ExtraICState extra_ic_state =
2341 SSE2Field::encode(sse2) |
2342 OpField::encode(op_ - FIRST_TOKEN) |
2343 OverwriteModeField::encode(mode_) |
2344 LeftKindField::encode(left_kind_) |
2345 ResultKindField::encode(result_kind_) |
2346 HasFixedRightArgField::encode(fixed_right_arg_.has_value);
2347 if (fixed_right_arg_.has_value) {
2348 extra_ic_state = FixedRightArgValueField::update(
2349 extra_ic_state, WhichPowerOf2(fixed_right_arg_.value));
2350 } else {
2351 extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
2352 }
2353 return extra_ic_state;
2354 }
2355
2356
2357 // static
2358 void BinaryOpIC::State::GenerateAheadOfTime(
2359 Isolate* isolate, void (*Generate)(Isolate*, const State&)) {
2360 // TODO(olivf) We should investigate why adding stubs to the snapshot is so
2361 // expensive at runtime. When solved we should be able to add most binops to
2362 // the snapshot instead of hand-picking them.
2363 // Generated list of commonly used stubs
2364 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \
2365 do { \
2366 State state(op, mode); \
2367 state.left_kind_ = left_kind; \
2368 state.fixed_right_arg_.has_value = false; \
2369 state.right_kind_ = right_kind; \
2370 state.result_kind_ = result_kind; \
2371 Generate(isolate, state); \
2372 } while (false)
2373 GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE);
2374 GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT);
2375 GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE);
2376 GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT);
2377 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2378 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2379 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
2380 GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE);
2381 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT);
2382 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT);
2383 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2384 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2385 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
2386 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2387 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2388 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2389 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2390 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2391 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2392 GENERATE(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE);
2393 GENERATE(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT);
2394 GENERATE(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE);
2395 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2396 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2397 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2398 GENERATE(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT);
2399 GENERATE(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT);
2400 GENERATE(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE);
2401 GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT);
2402 GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT);
2403 GENERATE(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE);
2404 GENERATE(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT);
2405 GENERATE(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE);
2406 GENERATE(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT);
2407 GENERATE(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE);
2408 GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT);
2409 GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT);
2410 GENERATE(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT);
2411 GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE);
2412 GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2413 GENERATE(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE);
2414 GENERATE(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT);
2415 GENERATE(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT);
2416 GENERATE(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE);
2417 GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT);
2418 GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT);
2419 GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT);
2420 GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT);
2421 GENERATE(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT);
2422 GENERATE(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE);
2423 GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT);
2424 GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2425 GENERATE(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE);
2426 GENERATE(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2427 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE);
2428 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT);
2429 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
2430 GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE);
2431 GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
2432 GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT);
2433 GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT);
2434 GENERATE(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT);
2435 GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT);
2436 GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2437 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE);
2438 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT);
2439 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT);
2440 GENERATE(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE);
2441 GENERATE(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT);
2442 GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE);
2443 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE);
2444 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT);
2445 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2446 GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE);
2447 GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE);
2448 GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE);
2449 GENERATE(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE);
2450 GENERATE(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT);
2451 GENERATE(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT);
2452 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE);
2453 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT);
2454 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2455 GENERATE(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE);
2456 GENERATE(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE);
2457 GENERATE(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2458 GENERATE(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2459 GENERATE(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE);
2460 GENERATE(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE);
2461 GENERATE(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2462 GENERATE(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2463 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2464 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2465 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2466 GENERATE(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2467 GENERATE(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2468 GENERATE(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE);
2469 GENERATE(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE);
2470 GENERATE(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT);
2471 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2472 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2473 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2474 GENERATE(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE);
2475 GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT);
2476 GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT);
2477 GENERATE(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE);
2478 GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT);
2479 GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT);
2480 GENERATE(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2481 GENERATE(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE);
2482 GENERATE(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT);
2483 GENERATE(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE);
2484 GENERATE(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE);
2485 GENERATE(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2486 GENERATE(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2487 GENERATE(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE);
2488 GENERATE(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT);
2489 GENERATE(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE);
2490 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2491 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2492 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
2493 GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2494 GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2495 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2496 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2497 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2498 GENERATE(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE);
2499 GENERATE(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT);
2500 GENERATE(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE);
2501 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2502 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2503 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2504 GENERATE(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE);
2505 GENERATE(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE);
2506 GENERATE(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT);
2507 GENERATE(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE);
2508 GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT);
2509 GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT);
2510 GENERATE(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2511 GENERATE(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE);
2512 GENERATE(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2513 GENERATE(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE);
2514 GENERATE(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2515 GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT);
2516 GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2517 GENERATE(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE);
2518 GENERATE(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT);
2519 GENERATE(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE);
2520 GENERATE(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT);
2521 GENERATE(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2522 GENERATE(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE);
2523 GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT);
2524 GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT);
2525 GENERATE(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE);
2526 GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT);
2527 GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT);
2528 GENERATE(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE);
2529 GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT);
2530 GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2531 GENERATE(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE);
2532 GENERATE(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
2533 GENERATE(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
2534 GENERATE(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE);
2535 GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT);
2536 GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2537 GENERATE(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE);
2538 GENERATE(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT);
2539 GENERATE(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2540 GENERATE(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
2541 GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT);
2542 GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT);
2543 GENERATE(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2544 GENERATE(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2545 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2546 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2547 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2548 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2549 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2550 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2551 GENERATE(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE);
2552 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2553 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2554 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2555 GENERATE(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE);
2556 GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT);
2557 GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT);
2558 #undef GENERATE
2559 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind, mode) \
2560 do { \
2561 State state(op, mode); \
2562 state.left_kind_ = left_kind; \
2563 state.fixed_right_arg_.has_value = true; \
2564 state.fixed_right_arg_.value = fixed_right_arg_value; \
2565 state.right_kind_ = SMI; \
2566 state.result_kind_ = result_kind; \
2567 Generate(isolate, state); \
2568 } while (false)
2569 GENERATE(Token::MOD, SMI, 2, SMI, NO_OVERWRITE);
2570 GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE);
2571 GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT);
2572 GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE);
2573 GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT);
2574 GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE);
2575 GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE);
2576 #undef GENERATE
2577 }
2578
2579
2580 Handle<Type> BinaryOpIC::State::GetResultType(Isolate* isolate) const {
2581 Kind result_kind = result_kind_;
2582 if (HasSideEffects()) {
2583 result_kind = NONE;
2584 } else if (result_kind == GENERIC && op_ == Token::ADD) {
2585 return handle(Type::Union(handle(Type::Number(), isolate),
2586 handle(Type::String(), isolate)), isolate);
2587 } else if (result_kind == NUMBER && op_ == Token::SHR) {
2588 return handle(Type::Unsigned32(), isolate);
2589 }
2590 ASSERT_NE(GENERIC, result_kind);
2591 return KindToType(result_kind, isolate);
2592 }
2593
2594
2595 void BinaryOpIC::State::Print(StringStream* stream) const {
2596 stream->Add("(%s", Token::Name(op_));
2597 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft");
2598 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight");
2599 stream->Add(":%s*", KindToString(left_kind_));
2600 if (fixed_right_arg_.has_value) {
2601 stream->Add("%d", fixed_right_arg_.value);
2602 } else {
2603 stream->Add("%s", KindToString(right_kind_));
2604 }
2605 stream->Add("->%s)", KindToString(result_kind_));
2606 }
2607
2608
2609 void BinaryOpIC::State::Update(Handle<Object> left,
2610 Handle<Object> right,
2611 Handle<Object> result) {
2612 ExtraICState old_extra_ic_state = GetExtraICState();
2613
2614 left_kind_ = UpdateKind(left, left_kind_);
2615 right_kind_ = UpdateKind(right, right_kind_);
2616
2617 int32_t fixed_right_arg_value = 0;
2618 bool has_fixed_right_arg =
2619 op_ == Token::MOD &&
2620 right->ToInt32(&fixed_right_arg_value) &&
2621 fixed_right_arg_value > 0 &&
2622 IsPowerOf2(fixed_right_arg_value) &&
2623 FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
2624 (left_kind_ == SMI || left_kind_ == INT32) &&
2625 (result_kind_ == NONE || !fixed_right_arg_.has_value);
2626 fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg,
2627 fixed_right_arg_value);
2628
2629 result_kind_ = UpdateKind(result, result_kind_);
2630
2631 if (!Token::IsTruncatingBinaryOp(op_)) {
2632 Kind input_kind = Max(left_kind_, right_kind_);
2633 if (result_kind_ < input_kind && input_kind <= NUMBER) {
2634 result_kind_ = input_kind;
2635 }
2636 }
2637
2638 // Reset overwrite mode unless we can actually make use of it, or may be able
2639 // to make use of it at some point in the future.
2640 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) ||
2641 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) ||
2642 result_kind_ > NUMBER) {
2643 mode_ = NO_OVERWRITE;
2644 }
2645
2646 if (old_extra_ic_state == GetExtraICState()) {
2647 // Tagged operations can lead to non-truncating HChanges
2648 if (left->IsUndefined() || left->IsBoolean()) {
2649 left_kind_ = GENERIC;
2650 } else if (right->IsUndefined() || right->IsBoolean()) {
2651 right_kind_ = GENERIC;
2652 } else {
2653 // Since the X87 is too precise, we might bail out on numbers which
2654 // actually would truncate with 64 bit precision.
2655 ASSERT(!CpuFeatures::IsSupported(SSE2));
2656 ASSERT(result_kind_ < NUMBER);
2657 result_kind_ = NUMBER;
2658 }
2659 }
2660 }
2661
2662
2663 BinaryOpIC::State::Kind BinaryOpIC::State::UpdateKind(Handle<Object> object,
2664 Kind kind) const {
2665 Kind new_kind = GENERIC;
2666 bool is_truncating = Token::IsTruncatingBinaryOp(op());
2667 if (object->IsBoolean() && is_truncating) {
2668 // Booleans will be automatically truncated by HChange.
2669 new_kind = INT32;
2670 } else if (object->IsUndefined()) {
2671 // Undefined will be automatically truncated by HChange.
2672 new_kind = is_truncating ? INT32 : NUMBER;
2673 } else if (object->IsSmi()) {
2674 new_kind = SMI;
2675 } else if (object->IsHeapNumber()) {
2676 double value = Handle<HeapNumber>::cast(object)->value();
2677 new_kind = TypeInfo::IsInt32Double(value) ? INT32 : NUMBER;
2678 } else if (object->IsString() && op() == Token::ADD) {
2679 new_kind = STRING;
2680 }
2681 if (new_kind == INT32 && SmiValuesAre32Bits()) {
2682 new_kind = NUMBER;
2683 }
2684 if (kind != NONE &&
2685 ((new_kind <= NUMBER && kind > NUMBER) ||
2686 (new_kind > NUMBER && kind <= NUMBER))) {
2687 new_kind = GENERIC;
2688 }
2689 return Max(kind, new_kind);
2690 }
2691
2692
2693 // static
2694 const char* BinaryOpIC::State::KindToString(Kind kind) {
2695 switch (kind) {
2696 case NONE: return "None";
2327 case SMI: return "Smi"; 2697 case SMI: return "Smi";
2328 case INT32: return "Int32"; 2698 case INT32: return "Int32";
2329 case NUMBER: return "Number"; 2699 case NUMBER: return "Number";
2330 case ODDBALL: return "Oddball";
2331 case STRING: return "String"; 2700 case STRING: return "String";
2332 case GENERIC: return "Generic"; 2701 case GENERIC: return "Generic";
2333 default: return "Invalid"; 2702 }
2334 } 2703 UNREACHABLE();
2704 return NULL;
2705 }
2706
2707
2708 // static
2709 Handle<Type> BinaryOpIC::State::KindToType(Kind kind, Isolate* isolate) {
2710 Type* type = NULL;
2711 switch (kind) {
2712 case NONE: type = Type::None(); break;
2713 case SMI: type = Type::Smi(); break;
2714 case INT32: type = Type::Signed32(); break;
2715 case NUMBER: type = Type::Number(); break;
2716 case STRING: type = Type::String(); break;
2717 case GENERIC: type = Type::Any(); break;
2718 }
2719 return handle(type, isolate);
2335 } 2720 }
2336 2721
2337 2722
2338 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { 2723 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
2339 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); 2724 State state(target()->extended_extra_ic_state());
2340 BinaryOpStub stub(extra_ic_state); 2725
2341 2726 // Compute the actual result using the builtin for the binary operation.
2342 Handle<Type> left_type = stub.GetLeftType(isolate()); 2727 Object* builtin = isolate()->js_builtins_object()->javascript_builtin(
2343 Handle<Type> right_type = stub.GetRightType(isolate()); 2728 TokenToJSBuiltin(state.op()));
2344 bool smi_was_enabled = left_type->Maybe(Type::Smi()) && 2729 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
2345 right_type->Maybe(Type::Smi()); 2730 bool caught_exception;
2346 2731 Handle<Object> result = Execution::Call(
2347 Maybe<Handle<Object> > result = stub.Result(left, right, isolate()); 2732 isolate(), function, left, 1, &right, &caught_exception);
2348 if (!result.has_value) return Failure::Exception(); 2733 if (caught_exception) return Failure::Exception();
2349 2734
2350 #ifdef DEBUG 2735 // Compute the new state.
2736 State old_state = state;
2737 state.Update(left, right, result);
2738
2739 // Install the new stub.
2740 BinaryOpICStub stub(state);
2741 set_target(*stub.GetCode(isolate()));
2742
2351 if (FLAG_trace_ic) { 2743 if (FLAG_trace_ic) {
2352 char buffer[100]; 2744 char buffer[150];
2353 NoAllocationStringAllocator allocator(buffer, 2745 NoAllocationStringAllocator allocator(
2354 static_cast<unsigned>(sizeof(buffer))); 2746 buffer, static_cast<unsigned>(sizeof(buffer)));
2355 StringStream stream(&allocator); 2747 StringStream stream(&allocator);
2356 stream.Add("["); 2748 stream.Add("[BinaryOpIC");
2357 stub.PrintName(&stream); 2749 old_state.Print(&stream);
2358
2359 stub.UpdateStatus(left, right, result);
2360
2361 stream.Add(" => "); 2750 stream.Add(" => ");
2362 stub.PrintState(&stream); 2751 state.Print(&stream);
2363 stream.Add(" "); 2752 stream.Add(" @ %p <- ", static_cast<void*>(*target()));
2364 stream.OutputToStdOut(); 2753 stream.OutputToStdOut();
2365 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate())));
2366 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); 2754 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2367 PrintF("]\n"); 2755 PrintF("]\n");
2368 } else { 2756 }
2369 stub.UpdateStatus(left, right, result); 2757
2370 } 2758 // Patch the inlined smi code as necessary.
2371 #else 2759 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) {
2372 stub.UpdateStatus(left, right, result);
2373 #endif
2374
2375 Handle<Code> code = stub.GetCode(isolate());
2376 set_target(*code);
2377
2378 left_type = stub.GetLeftType(isolate());
2379 right_type = stub.GetRightType(isolate());
2380 bool enable_smi = left_type->Maybe(Type::Smi()) &&
2381 right_type->Maybe(Type::Smi());
2382
2383 if (!smi_was_enabled && enable_smi) {
2384 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); 2760 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2385 } else if (smi_was_enabled && !enable_smi) { 2761 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) {
2386 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); 2762 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK);
2387 } 2763 }
2388 2764
2389 ASSERT(result.has_value); 2765 return *result;
2390 return static_cast<MaybeObject*>(*result.value);
2391 } 2766 }
2392 2767
2393 2768
2394 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { 2769 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2395 HandleScope scope(isolate); 2770 HandleScope scope(isolate);
2396 Handle<Object> left = args.at<Object>(0); 2771 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
2397 Handle<Object> right = args.at<Object>(1); 2772 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
2398 BinaryOpIC ic(isolate); 2773 BinaryOpIC ic(isolate);
2399 return ic.Transition(left, right); 2774 return ic.Transition(left, right);
2400 } 2775 }
2401 2776
2402 2777
2403 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { 2778 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2404 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2779 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2405 Code* code = NULL; 2780 Code* code = NULL;
2406 CHECK(stub.FindCodeInCache(&code, isolate)); 2781 CHECK(stub.FindCodeInCache(&code, isolate));
2407 return code; 2782 return code;
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
2592 State state = TargetState(previous_state, previous_left, previous_right, 2967 State state = TargetState(previous_state, previous_left, previous_right,
2593 HasInlinedSmiCode(address()), x, y); 2968 HasInlinedSmiCode(address()), x, y);
2594 ICCompareStub stub(op_, new_left, new_right, state); 2969 ICCompareStub stub(op_, new_left, new_right, state);
2595 if (state == KNOWN_OBJECT) { 2970 if (state == KNOWN_OBJECT) {
2596 stub.set_known_map( 2971 stub.set_known_map(
2597 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); 2972 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
2598 } 2973 }
2599 Handle<Code> new_target = stub.GetCode(isolate()); 2974 Handle<Code> new_target = stub.GetCode(isolate());
2600 set_target(*new_target); 2975 set_target(*new_target);
2601 2976
2602 #ifdef DEBUG
2603 if (FLAG_trace_ic) { 2977 if (FLAG_trace_ic) {
2604 PrintF("[CompareIC in "); 2978 PrintF("[CompareIC in ");
2605 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); 2979 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2606 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", 2980 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2607 GetStateName(previous_left), 2981 GetStateName(previous_left),
2608 GetStateName(previous_right), 2982 GetStateName(previous_right),
2609 GetStateName(previous_state), 2983 GetStateName(previous_state),
2610 GetStateName(new_left), 2984 GetStateName(new_left),
2611 GetStateName(new_right), 2985 GetStateName(new_right),
2612 GetStateName(state), 2986 GetStateName(state),
2613 Token::Name(op_), 2987 Token::Name(op_),
2614 static_cast<void*>(*stub.GetCode(isolate()))); 2988 static_cast<void*>(*stub.GetCode(isolate())));
2615 } 2989 }
2616 #endif
2617 2990
2618 // Activate inlined smi code. 2991 // Activate inlined smi code.
2619 if (previous_state == UNINITIALIZED) { 2992 if (previous_state == UNINITIALIZED) {
2620 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); 2993 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2621 } 2994 }
2622 2995
2623 return *new_target; 2996 return *new_target;
2624 } 2997 }
2625 2998
2626 2999
2627 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. 3000 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2628 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 3001 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2629 HandleScope scope(isolate); 3002 HandleScope scope(isolate);
2630 ASSERT(args.length() == 3); 3003 ASSERT(args.length() == 3);
2631 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 3004 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2632 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 3005 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2633 } 3006 }
2634 3007
2635 3008
2636 void CompareNilIC::Clear(Address address, Code* target) { 3009 void CompareNilIC::Clear(Address address, Code* target) {
2637 if (IsCleared(target)) return; 3010 if (IsCleared(target)) return;
2638 Code::ExtraICState state = target->extended_extra_ic_state(); 3011 ExtraICState state = target->extended_extra_ic_state();
2639 3012
2640 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); 3013 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
2641 stub.ClearState(); 3014 stub.ClearState();
2642 3015
2643 Code* code = NULL; 3016 Code* code = NULL;
2644 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); 3017 CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
2645 3018
2646 SetTargetAtAddress(address, code); 3019 SetTargetAtAddress(address, code);
2647 } 3020 }
2648 3021
2649 3022
2650 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, 3023 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil,
2651 Handle<Object> object) { 3024 Handle<Object> object) {
2652 if (object->IsNull() || object->IsUndefined()) { 3025 if (object->IsNull() || object->IsUndefined()) {
2653 return Smi::FromInt(true); 3026 return Smi::FromInt(true);
2654 } 3027 }
2655 return Smi::FromInt(object->IsUndetectableObject()); 3028 return Smi::FromInt(object->IsUndetectableObject());
2656 } 3029 }
2657 3030
2658 3031
2659 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { 3032 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
2660 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); 3033 ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2661 3034
2662 CompareNilICStub stub(extra_ic_state); 3035 CompareNilICStub stub(extra_ic_state);
2663 3036
2664 // Extract the current supported types from the patched IC and calculate what 3037 // Extract the current supported types from the patched IC and calculate what
2665 // types must be supported as a result of the miss. 3038 // types must be supported as a result of the miss.
2666 bool already_monomorphic = stub.IsMonomorphic(); 3039 bool already_monomorphic = stub.IsMonomorphic();
2667 3040
2668 stub.UpdateStatus(object); 3041 stub.UpdateStatus(object);
2669 3042
2670 NilValue nil = stub.GetNilValue(); 3043 NilValue nil = stub.GetNilValue();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2765 #undef ADDR 3138 #undef ADDR
2766 }; 3139 };
2767 3140
2768 3141
2769 Address IC::AddressFromUtilityId(IC::UtilityId id) { 3142 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2770 return IC_utilities[id]; 3143 return IC_utilities[id];
2771 } 3144 }
2772 3145
2773 3146
2774 } } // namespace v8::internal 3147 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698