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

Side by Side Diff: src/ic.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 months 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/incremental-marking.cc » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 case kStringCharCodeAt: 571 case kStringCharCodeAt:
572 case kStringCharAt: 572 case kStringCharAt:
573 if (object->IsString()) { 573 if (object->IsString()) {
574 String* string = String::cast(*object); 574 String* string = String::cast(*object);
575 // Check there's the right string value or wrapper in the receiver slot. 575 // Check there's the right string value or wrapper in the receiver slot.
576 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); 576 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
577 // If we're in the default (fastest) state and the index is 577 // If we're in the default (fastest) state and the index is
578 // out of bounds, update the state to record this fact. 578 // out of bounds, update the state to record this fact.
579 if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB && 579 if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB &&
580 argc >= 1 && args[1]->IsNumber()) { 580 argc >= 1 && args[1]->IsNumber()) {
581 double index; 581 double index = DoubleToInteger(args.number_at(1));
582 if (args[1]->IsSmi()) {
583 index = Smi::cast(args[1])->value();
584 } else {
585 ASSERT(args[1]->IsHeapNumber());
586 index = DoubleToInteger(HeapNumber::cast(args[1])->value());
587 }
588 if (index < 0 || index >= string->length()) { 582 if (index < 0 || index >= string->length()) {
589 *extra_ic_state = 583 *extra_ic_state =
590 StringStubState::update(*extra_ic_state, 584 StringStubState::update(*extra_ic_state,
591 STRING_INDEX_OUT_OF_BOUNDS); 585 STRING_INDEX_OUT_OF_BOUNDS);
592 return true; 586 return true;
593 } 587 }
594 } 588 }
595 } 589 }
596 break; 590 break;
597 default: 591 default:
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 return CallICBase::LoadFunction(state, 786 return CallICBase::LoadFunction(state,
793 Code::kNoExtraICState, 787 Code::kNoExtraICState,
794 object, 788 object,
795 Handle<String>::cast(key)); 789 Handle<String>::cast(key));
796 } 790 }
797 791
798 if (object->IsUndefined() || object->IsNull()) { 792 if (object->IsUndefined() || object->IsNull()) {
799 return TypeError("non_object_property_call", object, key); 793 return TypeError("non_object_property_call", object, key);
800 } 794 }
801 795
802 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { 796 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) {
803 int argc = target()->arguments_count(); 797 int argc = target()->arguments_count();
804 InLoopFlag in_loop = target()->ic_in_loop(); 798 InLoopFlag in_loop = target()->ic_in_loop();
805 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( 799 Heap* heap = Handle<HeapObject>::cast(object)->GetHeap();
806 argc, in_loop, Code::KEYED_CALL_IC, Code::kNoExtraICState); 800 Map* map = heap->non_strict_arguments_elements_map();
807 Object* code; 801 if (object->IsJSObject() &&
808 if (maybe_code->ToObject(&code)) { 802 Handle<JSObject>::cast(object)->elements()->map() == map) {
809 set_target(Code::cast(code)); 803 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments(
804 argc, in_loop, Code::KEYED_CALL_IC);
805 Object* code;
806 if (maybe_code->ToObject(&code)) {
807 set_target(Code::cast(code));
810 #ifdef DEBUG 808 #ifdef DEBUG
811 TraceIC( 809 TraceIC(
812 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); 810 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
813 #endif 811 #endif
812 }
813 } else if (FLAG_use_ic && state != MEGAMORPHIC &&
814 !object->IsAccessCheckNeeded()) {
815 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
816 argc, in_loop, Code::KEYED_CALL_IC, Code::kNoExtraICState);
817 Object* code;
818 if (maybe_code->ToObject(&code)) {
819 set_target(Code::cast(code));
820 #ifdef DEBUG
821 TraceIC(
822 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
823 #endif
824 }
814 } 825 }
815 } 826 }
816 827
817 HandleScope scope(isolate()); 828 HandleScope scope(isolate());
818 Handle<Object> result = GetProperty(object, key); 829 Handle<Object> result = GetProperty(object, key);
819 RETURN_IF_EMPTY_HANDLE(isolate(), result); 830 RETURN_IF_EMPTY_HANDLE(isolate(), result);
820 831
821 // Make receiver an object if the callee requires it. Strict mode or builtin 832 // Make receiver an object if the callee requires it. Strict mode or builtin
822 // functions do not wrap the receiver, non-strict functions and objects 833 // functions do not wrap the receiver, non-strict functions and objects
823 // called as functions do. 834 // called as functions do.
(...skipping 18 matching lines...) Expand all
842 MaybeObject* LoadIC::Load(State state, 853 MaybeObject* LoadIC::Load(State state,
843 Handle<Object> object, 854 Handle<Object> object,
844 Handle<String> name) { 855 Handle<String> name) {
845 // If the object is undefined or null it's illegal to try to get any 856 // If the object is undefined or null it's illegal to try to get any
846 // of its properties; throw a TypeError in that case. 857 // of its properties; throw a TypeError in that case.
847 if (object->IsUndefined() || object->IsNull()) { 858 if (object->IsUndefined() || object->IsNull()) {
848 return TypeError("non_object_property_load", object, name); 859 return TypeError("non_object_property_load", object, name);
849 } 860 }
850 861
851 if (FLAG_use_ic) { 862 if (FLAG_use_ic) {
852 Code* non_monomorphic_stub =
853 (state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub();
854
855 // Use specialized code for getting the length of strings and 863 // Use specialized code for getting the length of strings and
856 // string wrapper objects. The length property of string wrapper 864 // string wrapper objects. The length property of string wrapper
857 // objects is read-only and therefore always returns the length of 865 // objects is read-only and therefore always returns the length of
858 // the underlying string value. See ECMA-262 15.5.5.1. 866 // the underlying string value. See ECMA-262 15.5.5.1.
859 if ((object->IsString() || object->IsStringWrapper()) && 867 if ((object->IsString() || object->IsStringWrapper()) &&
860 name->Equals(isolate()->heap()->length_symbol())) { 868 name->Equals(isolate()->heap()->length_symbol())) {
861 HandleScope scope(isolate()); 869 AssertNoAllocation no_allocation;
862 #ifdef DEBUG 870 Code* stub = NULL;
863 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); 871 if (state == UNINITIALIZED) {
864 #endif 872 stub = pre_monomorphic_stub();
865 if (state == PREMONOMORPHIC) { 873 } else if (state == PREMONOMORPHIC) {
866 if (object->IsString()) { 874 if (object->IsString()) {
867 set_target(isolate()->builtins()->builtin( 875 stub = isolate()->builtins()->builtin(
868 Builtins::kLoadIC_StringLength)); 876 Builtins::kLoadIC_StringLength);
869 } else { 877 } else {
870 set_target(isolate()->builtins()->builtin( 878 stub = isolate()->builtins()->builtin(
871 Builtins::kLoadIC_StringWrapperLength)); 879 Builtins::kLoadIC_StringWrapperLength);
872 } 880 }
873 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { 881 } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
874 set_target(isolate()->builtins()->builtin( 882 stub = isolate()->builtins()->builtin(
875 Builtins::kLoadIC_StringWrapperLength)); 883 Builtins::kLoadIC_StringWrapperLength);
876 } else { 884 } else if (state != MEGAMORPHIC) {
877 set_target(non_monomorphic_stub); 885 stub = megamorphic_stub();
886 }
887 if (stub != NULL) {
888 set_target(stub);
889 #ifdef DEBUG
890 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
891 #endif
878 } 892 }
879 // Get the string if we have a string wrapper object. 893 // Get the string if we have a string wrapper object.
880 if (object->IsJSValue()) { 894 if (object->IsJSValue()) {
881 object = Handle<Object>(Handle<JSValue>::cast(object)->value(), 895 return Smi::FromInt(
882 isolate()); 896 String::cast(Handle<JSValue>::cast(object)->value())->length());
883 } 897 }
884 return Smi::FromInt(String::cast(*object)->length()); 898 return Smi::FromInt(String::cast(*object)->length());
885 } 899 }
886 900
887 // Use specialized code for getting the length of arrays. 901 // Use specialized code for getting the length of arrays.
888 if (object->IsJSArray() && 902 if (object->IsJSArray() &&
889 name->Equals(isolate()->heap()->length_symbol())) { 903 name->Equals(isolate()->heap()->length_symbol())) {
904 AssertNoAllocation no_allocation;
905 Code* stub = NULL;
906 if (state == UNINITIALIZED) {
907 stub = pre_monomorphic_stub();
908 } else if (state == PREMONOMORPHIC) {
909 stub = isolate()->builtins()->builtin(
910 Builtins::kLoadIC_ArrayLength);
911 } else if (state != MEGAMORPHIC) {
912 stub = megamorphic_stub();
913 }
914 if (stub != NULL) {
915 set_target(stub);
890 #ifdef DEBUG 916 #ifdef DEBUG
891 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); 917 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
892 #endif 918 #endif
893 if (state == PREMONOMORPHIC) {
894 set_target(isolate()->builtins()->builtin(
895 Builtins::kLoadIC_ArrayLength));
896 } else {
897 set_target(non_monomorphic_stub);
898 } 919 }
899 return JSArray::cast(*object)->length(); 920 return JSArray::cast(*object)->length();
900 } 921 }
901 922
902 // Use specialized code for getting prototype of functions. 923 // Use specialized code for getting prototype of functions.
903 if (object->IsJSFunction() && 924 if (object->IsJSFunction() &&
904 name->Equals(isolate()->heap()->prototype_symbol()) && 925 name->Equals(isolate()->heap()->prototype_symbol()) &&
905 JSFunction::cast(*object)->should_have_prototype()) { 926 JSFunction::cast(*object)->should_have_prototype()) {
927 { AssertNoAllocation no_allocation;
928 Code* stub = NULL;
929 if (state == UNINITIALIZED) {
930 stub = pre_monomorphic_stub();
931 } else if (state == PREMONOMORPHIC) {
932 stub = isolate()->builtins()->builtin(
933 Builtins::kLoadIC_FunctionPrototype);
934 } else if (state != MEGAMORPHIC) {
935 stub = megamorphic_stub();
936 }
937 if (stub != NULL) {
938 set_target(stub);
906 #ifdef DEBUG 939 #ifdef DEBUG
907 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); 940 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
908 #endif 941 #endif
909 if (state == PREMONOMORPHIC) { 942 }
910 set_target(isolate()->builtins()->builtin(
911 Builtins::kLoadIC_FunctionPrototype));
912 } else {
913 set_target(non_monomorphic_stub);
914 } 943 }
915 return Accessors::FunctionGetPrototype(*object, 0); 944 return Accessors::FunctionGetPrototype(*object, 0);
916 } 945 }
917 } 946 }
918 947
919 // Check if the name is trivially convertible to an index and get 948 // Check if the name is trivially convertible to an index and get
920 // the element if so. 949 // the element if so.
921 uint32_t index; 950 uint32_t index;
922 if (name->AsArrayIndex(&index)) return object->GetElement(index); 951 if (name->AsArrayIndex(&index)) return object->GetElement(index);
923 952
924 // Named lookup in the object. 953 // Named lookup in the object.
925 LookupResult lookup; 954 LookupResult lookup;
926 LookupForRead(*object, *name, &lookup); 955 LookupForRead(*object, *name, &lookup);
927 956
928 // If we did not find a property, check if we need to throw an exception. 957 // If we did not find a property, check if we need to throw an exception.
929 if (!lookup.IsProperty()) { 958 if (!lookup.IsProperty()) {
930 if (FLAG_strict || IsContextual(object)) { 959 if (IsContextual(object)) {
931 return ReferenceError("not_defined", name); 960 return ReferenceError("not_defined", name);
932 } 961 }
933 LOG(isolate(), SuspectReadEvent(*name, *object)); 962 LOG(isolate(), SuspectReadEvent(*name, *object));
934 } 963 }
935 964
936 // Update inline cache and stub cache. 965 // Update inline cache and stub cache.
937 if (FLAG_use_ic) { 966 if (FLAG_use_ic) {
938 UpdateCaches(&lookup, state, object, name); 967 UpdateCaches(&lookup, state, object, name);
939 } 968 }
940 969
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 1090
1062 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); 1091 isolate()->stub_cache()->Set(*name, map, Code::cast(code));
1063 } 1092 }
1064 1093
1065 #ifdef DEBUG 1094 #ifdef DEBUG
1066 TraceIC("LoadIC", name, state, target()); 1095 TraceIC("LoadIC", name, state, target());
1067 #endif 1096 #endif
1068 } 1097 }
1069 1098
1070 1099
1071 String* KeyedLoadIC::GetStubNameForCache(IC::State ic_state) { 1100 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck(
1072 if (ic_state == MONOMORPHIC) { 1101 bool is_js_array,
1073 return isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol(); 1102 JSObject::ElementsKind elements_kind) {
1074 } else { 1103 return KeyedLoadElementStub(elements_kind).TryGetCode();
1075 ASSERT(ic_state == MEGAMORPHIC);
1076 return isolate()->heap()->KeyedLoadSpecializedPolymorphic_symbol();
1077 }
1078 }
1079
1080
1081 MaybeObject* KeyedLoadIC::GetFastElementStubWithoutMapCheck(
1082 bool is_js_array) {
1083 return KeyedLoadFastElementStub().TryGetCode();
1084 }
1085
1086
1087 MaybeObject* KeyedLoadIC::GetExternalArrayStubWithoutMapCheck(
1088 ExternalArrayType array_type) {
1089 return KeyedLoadExternalArrayStub(array_type).TryGetCode();
1090 } 1104 }
1091 1105
1092 1106
1093 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub( 1107 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub(
1094 MapList* receiver_maps, 1108 MapList* receiver_maps,
1095 CodeList* targets, 1109 CodeList* targets,
1096 StrictModeFlag strict_mode) { 1110 StrictModeFlag strict_mode) {
1097 Object* object; 1111 Object* object;
1098 KeyedLoadStubCompiler compiler; 1112 KeyedLoadStubCompiler compiler;
1099 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps, 1113 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 // Rewrite to the generic keyed load stub. 1208 // Rewrite to the generic keyed load stub.
1195 if (FLAG_use_ic) set_target(generic_stub()); 1209 if (FLAG_use_ic) set_target(generic_stub());
1196 return Runtime::GetElementOrCharAt(isolate(), object, index); 1210 return Runtime::GetElementOrCharAt(isolate(), object, index);
1197 } 1211 }
1198 1212
1199 // Named lookup. 1213 // Named lookup.
1200 LookupResult lookup; 1214 LookupResult lookup;
1201 LookupForRead(*object, *name, &lookup); 1215 LookupForRead(*object, *name, &lookup);
1202 1216
1203 // If we did not find a property, check if we need to throw an exception. 1217 // If we did not find a property, check if we need to throw an exception.
1204 if (!lookup.IsProperty()) { 1218 if (!lookup.IsProperty() && IsContextual(object)) {
1205 if (FLAG_strict || IsContextual(object)) { 1219 return ReferenceError("not_defined", name);
1206 return ReferenceError("not_defined", name);
1207 }
1208 } 1220 }
1209 1221
1210 if (FLAG_use_ic) { 1222 if (FLAG_use_ic) {
1211 UpdateCaches(&lookup, state, object, name); 1223 UpdateCaches(&lookup, state, object, name);
1212 } 1224 }
1213 1225
1214 PropertyAttributes attr; 1226 PropertyAttributes attr;
1215 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { 1227 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
1216 // Get the property. 1228 // Get the property.
1217 Object* result; 1229 Object* result;
(...skipping 18 matching lines...) Expand all
1236 1248
1237 if (use_ic) { 1249 if (use_ic) {
1238 Code* stub = generic_stub(); 1250 Code* stub = generic_stub();
1239 if (!force_generic_stub) { 1251 if (!force_generic_stub) {
1240 if (object->IsString() && key->IsNumber()) { 1252 if (object->IsString() && key->IsNumber()) {
1241 if (state == UNINITIALIZED) { 1253 if (state == UNINITIALIZED) {
1242 stub = string_stub(); 1254 stub = string_stub();
1243 } 1255 }
1244 } else if (object->IsJSObject()) { 1256 } else if (object->IsJSObject()) {
1245 JSObject* receiver = JSObject::cast(*object); 1257 JSObject* receiver = JSObject::cast(*object);
1246 if (receiver->HasIndexedInterceptor()) { 1258 Heap* heap = Handle<JSObject>::cast(object)->GetHeap();
1259 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map();
1260 if (elements_map == heap->non_strict_arguments_elements_map()) {
1261 stub = non_strict_arguments_stub();
1262 } else if (receiver->HasIndexedInterceptor()) {
1247 stub = indexed_interceptor_stub(); 1263 stub = indexed_interceptor_stub();
1248 } else if (key->IsSmi()) { 1264 } else if (key->IsSmi() && (target() != non_strict_arguments_stub())) {
1249 MaybeObject* maybe_stub = ComputeStub(receiver, 1265 MaybeObject* maybe_stub = ComputeStub(receiver,
1250 false, 1266 false,
1251 kNonStrictMode, 1267 kNonStrictMode,
1252 stub); 1268 stub);
1253 stub = maybe_stub->IsFailure() ? 1269 stub = maybe_stub->IsFailure() ?
1254 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); 1270 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1255 } 1271 }
1256 } 1272 }
1257 } 1273 }
1258 if (stub != NULL) set_target(stub); 1274 if (stub != NULL) set_target(stub);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; 1364 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;
1349 1365
1350 // If the property is read-only, we leave the IC in its current 1366 // If the property is read-only, we leave the IC in its current
1351 // state. 1367 // state.
1352 if (lookup->IsReadOnly()) return false; 1368 if (lookup->IsReadOnly()) return false;
1353 1369
1354 return true; 1370 return true;
1355 } 1371 }
1356 1372
1357 1373
1358 static bool LookupForWrite(JSObject* object, 1374 static bool LookupForWrite(JSReceiver* receiver,
1359 String* name, 1375 String* name,
1360 LookupResult* lookup) { 1376 LookupResult* lookup) {
1361 object->LocalLookup(name, lookup); 1377 receiver->LocalLookup(name, lookup);
1362 if (!StoreICableLookup(lookup)) { 1378 if (!StoreICableLookup(lookup)) {
1363 return false; 1379 return false;
1364 } 1380 }
1365 1381
1366 if (lookup->type() == INTERCEPTOR) { 1382 if (lookup->type() == INTERCEPTOR) {
1383 JSObject* object = JSObject::cast(receiver);
1367 if (object->GetNamedInterceptor()->setter()->IsUndefined()) { 1384 if (object->GetNamedInterceptor()->setter()->IsUndefined()) {
1368 object->LocalLookupRealNamedProperty(name, lookup); 1385 object->LocalLookupRealNamedProperty(name, lookup);
1369 return StoreICableLookup(lookup); 1386 return StoreICableLookup(lookup);
1370 } 1387 }
1371 } 1388 }
1372 1389
1373 return true; 1390 return true;
1374 } 1391 }
1375 1392
1376 1393
1377 MaybeObject* StoreIC::Store(State state, 1394 MaybeObject* StoreIC::Store(State state,
1378 StrictModeFlag strict_mode, 1395 StrictModeFlag strict_mode,
1379 Handle<Object> object, 1396 Handle<Object> object,
1380 Handle<String> name, 1397 Handle<String> name,
1381 Handle<Object> value) { 1398 Handle<Object> value) {
1382 // If the object is undefined or null it's illegal to try to set any 1399 // If the object is undefined or null it's illegal to try to set any
1383 // properties on it; throw a TypeError in that case. 1400 // properties on it; throw a TypeError in that case.
1384 if (object->IsUndefined() || object->IsNull()) { 1401 if (object->IsUndefined() || object->IsNull()) {
1385 return TypeError("non_object_property_store", object, name); 1402 return TypeError("non_object_property_store", object, name);
1386 } 1403 }
1387 1404
1388 if (!object->IsJSObject()) { 1405 if (!object->IsJSReceiver()) {
1389 // The length property of string values is read-only. Throw in strict mode. 1406 // The length property of string values is read-only. Throw in strict mode.
1390 if (strict_mode == kStrictMode && object->IsString() && 1407 if (strict_mode == kStrictMode && object->IsString() &&
1391 name->Equals(isolate()->heap()->length_symbol())) { 1408 name->Equals(isolate()->heap()->length_symbol())) {
1392 return TypeError("strict_read_only_property", object, name); 1409 return TypeError("strict_read_only_property", object, name);
1393 } 1410 }
1394 // Ignore stores where the receiver is not a JSObject. 1411 // Ignore stores where the receiver is not a JSObject.
1395 return *value; 1412 return *value;
1396 } 1413 }
1397 1414
1415 // Handle proxies.
1416 if (object->IsJSProxy()) {
1417 return JSReceiver::cast(*object)->
1418 SetProperty(*name, *value, NONE, strict_mode);
1419 }
1420
1398 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1421 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1399 1422
1400 // Check if the given name is an array index. 1423 // Check if the given name is an array index.
1401 uint32_t index; 1424 uint32_t index;
1402 if (name->AsArrayIndex(&index)) { 1425 if (name->AsArrayIndex(&index)) {
1403 HandleScope scope(isolate()); 1426 HandleScope scope(isolate());
1404 Handle<Object> result = SetElement(receiver, index, value, strict_mode); 1427 Handle<Object> result = SetElement(receiver, index, value, strict_mode);
1405 if (result.is_null()) return Failure::Exception(); 1428 if (result.is_null()) return Failure::Exception();
1406 return *value; 1429 return *value;
1407 } 1430 }
1408 1431
1409 // Use specialized code for setting the length of arrays. 1432 // Use specialized code for setting the length of arrays.
1410 if (receiver->IsJSArray() 1433 if (receiver->IsJSArray()
1411 && name->Equals(isolate()->heap()->length_symbol()) 1434 && name->Equals(isolate()->heap()->length_symbol())
1412 && receiver->AllowsSetElementsLength()) { 1435 && JSArray::cast(*receiver)->AllowsSetElementsLength()) {
1413 #ifdef DEBUG 1436 #ifdef DEBUG
1414 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); 1437 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1415 #endif 1438 #endif
1416 Builtins::Name target = (strict_mode == kStrictMode) 1439 Builtins::Name target = (strict_mode == kStrictMode)
1417 ? Builtins::kStoreIC_ArrayLength_Strict 1440 ? Builtins::kStoreIC_ArrayLength_Strict
1418 : Builtins::kStoreIC_ArrayLength; 1441 : Builtins::kStoreIC_ArrayLength;
1419 set_target(isolate()->builtins()->builtin(target)); 1442 set_target(isolate()->builtins()->builtin(target));
1420 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1443 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1421 } 1444 }
1422 1445
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 } 1612 }
1590 } 1613 }
1591 } 1614 }
1592 1615
1593 1616
1594 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, 1617 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
1595 bool is_store, 1618 bool is_store,
1596 StrictModeFlag strict_mode, 1619 StrictModeFlag strict_mode,
1597 Code* generic_stub) { 1620 Code* generic_stub) {
1598 State ic_state = target()->ic_state(); 1621 State ic_state = target()->ic_state();
1599 Code* monomorphic_stub; 1622 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1600 // Always compute the MONOMORPHIC stub, even if the MEGAMORPHIC stub ends up 1623 Code* monomorphic_stub;
1601 // being used. This is necessary because the megamorphic stub needs to have 1624 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver,
1602 // access to more information than what is stored in the receiver map in some 1625 is_store,
1603 // cases (external arrays need the array type from the MONOMORPHIC stub). 1626 strict_mode,
1604 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver, 1627 generic_stub);
1605 is_store, 1628 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
1606 strict_mode,
1607 generic_stub);
1608 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
1609 1629
1610 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1611 return monomorphic_stub; 1630 return monomorphic_stub;
1612 } 1631 }
1613 ASSERT(target() != generic_stub); 1632 ASSERT(target() != generic_stub);
1614 1633
1615 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS 1634 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1616 // via megamorphic stubs, since they don't have a map in their relocation info 1635 // via megamorphic stubs, since they don't have a map in their relocation info
1617 // and so the stubs can't be harvested for the object needed for a map check. 1636 // and so the stubs can't be harvested for the object needed for a map check.
1618 if (target()->type() != NORMAL) { 1637 if (target()->type() != NORMAL) {
1619 return generic_stub; 1638 return generic_stub;
1620 } 1639 }
1621 1640
1622 // Determine the list of receiver maps that this call site has seen, 1641 // Determine the list of receiver maps that this call site has seen,
1623 // adding the map that was just encountered. 1642 // adding the map that was just encountered.
1624 MapList target_receiver_maps; 1643 MapList target_receiver_maps;
1625 GetReceiverMapsForStub(target(), &target_receiver_maps); 1644 GetReceiverMapsForStub(target(), &target_receiver_maps);
1626 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map())) { 1645 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map())) {
1627 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub 1646 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
1628 // won't help, use the generic stub. 1647 // won't help, use the generic stub.
1629 return generic_stub; 1648 return generic_stub;
1630 } 1649 }
1631 1650
1632 // TODO(1385): Currently MEGAMORPHIC stubs are cached in the receiver map stub 1651 // If the maximum number of receiver maps has been exceeded, use the generic
1633 // cache, but that can put receiver types together from unrelated call sites 1652 // version of the IC.
1634 // into the same stub--they always handle the union of all receiver maps seen 1653 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1635 // at all call sites involving the receiver map. This is only an 1654 return generic_stub;
1636 // approximation: ideally, there would be a global cache that mapped sets of 1655 }
1637 // receiver maps to MEGAMORPHIC stubs. The complexity of the MEGAMORPHIC stub 1656
1638 // computation also leads to direct manipulation of the stub cache from the IC 1657 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache();
1639 // code, which the global cache solution would avoid. 1658 Code::Flags flags = Code::ComputeFlags(this->kind(),
1640 Code::Kind kind = this->kind();
1641 Code::Flags flags = Code::ComputeFlags(kind,
1642 NOT_IN_LOOP, 1659 NOT_IN_LOOP,
1643 MEGAMORPHIC, 1660 MEGAMORPHIC,
1644 strict_mode); 1661 strict_mode);
1645 String* megamorphic_name = GetStubNameForCache(MEGAMORPHIC); 1662 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags);
1646 Object* maybe_cached_stub = receiver->map()->FindInCodeCache(megamorphic_name, 1663 // If there is a cached stub, use it.
1647 flags);
1648
1649 // Create a set of all receiver maps that have been seen at the IC call site
1650 // and those seen by the MEGAMORPHIC cached stub, if that's the stub that's
1651 // been selected.
1652 MapList receiver_maps;
1653 if (!maybe_cached_stub->IsUndefined()) { 1664 if (!maybe_cached_stub->IsUndefined()) {
1654 GetReceiverMapsForStub(Code::cast(maybe_cached_stub), &receiver_maps);
1655 }
1656 bool added_map = false;
1657 for (int i = 0; i < target_receiver_maps.length(); ++i) {
1658 if (AddOneReceiverMapIfMissing(&receiver_maps,
1659 target_receiver_maps.at(i))) {
1660 added_map = true;
1661 }
1662 }
1663 ASSERT(receiver_maps.length() > 0);
1664
1665 // If the maximum number of receiver maps has been exceeded, use the Generic
1666 // version of the IC.
1667 if (receiver_maps.length() > KeyedIC::kMaxKeyedPolymorphism) {
1668 return generic_stub;
1669 }
1670
1671 // If no maps have been seen at the call site that aren't in the cached
1672 // stub, then use it.
1673 if (!added_map) {
1674 ASSERT(!maybe_cached_stub->IsUndefined());
1675 ASSERT(maybe_cached_stub->IsCode()); 1665 ASSERT(maybe_cached_stub->IsCode());
1676 return Code::cast(maybe_cached_stub); 1666 return Code::cast(maybe_cached_stub);
1677 } 1667 }
1678 1668 // Collect MONOMORPHIC stubs for all target_receiver_maps.
1679 // Lookup all of the receiver maps in the cache, they should all already 1669 CodeList handler_ics(target_receiver_maps.length());
1680 // have MONOMORPHIC stubs. 1670 for (int i = 0; i < target_receiver_maps.length(); ++i) {
1681 CodeList handler_ics(KeyedIC::kMaxKeyedPolymorphism); 1671 Map* receiver_map(target_receiver_maps.at(i));
1682 for (int current = 0; current < receiver_maps.length(); ++current) {
1683 Map* receiver_map(receiver_maps.at(current));
1684 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( 1672 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1685 receiver_map, 1673 receiver_map, strict_mode);
1686 strict_mode,
1687 generic_stub);
1688 Code* cached_stub; 1674 Code* cached_stub;
1689 if (!maybe_cached_stub->To(&cached_stub)) { 1675 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
1690 return maybe_cached_stub;
1691 }
1692 handler_ics.Add(cached_stub); 1676 handler_ics.Add(cached_stub);
1693 } 1677 }
1694 1678 // Build the MEGAMORPHIC stub.
1695 Code* stub; 1679 Code* stub;
1696 // Build the MEGAMORPHIC stub. 1680 MaybeObject* maybe_stub = ConstructMegamorphicStub(&target_receiver_maps,
1697 maybe_stub = ConstructMegamorphicStub(&receiver_maps, 1681 &handler_ics,
1698 &handler_ics, 1682 strict_mode);
1699 strict_mode);
1700 if (!maybe_stub->To(&stub)) return maybe_stub; 1683 if (!maybe_stub->To(&stub)) return maybe_stub;
1701 1684 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub);
1702 MaybeObject* maybe_update = receiver->UpdateMapCodeCache(
1703 megamorphic_name,
1704 stub);
1705 if (maybe_update->IsFailure()) return maybe_update; 1685 if (maybe_update->IsFailure()) return maybe_update;
1706 return stub; 1686 return stub;
1707 } 1687 }
1708 1688
1709 1689
1710 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( 1690 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
1711 Map* receiver_map, 1691 Map* receiver_map,
1712 StrictModeFlag strict_mode, 1692 StrictModeFlag strict_mode) {
1713 Code* generic_stub) {
1714 if ((receiver_map->instance_type() & kNotStringTag) == 0) { 1693 if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1715 ASSERT(string_stub() != NULL); 1694 ASSERT(string_stub() != NULL);
1716 return string_stub(); 1695 return string_stub();
1717 } else if (receiver_map->has_external_array_elements()) { 1696 } else {
1718 // Determine the array type from the default MONOMORPHIC already generated 1697 ASSERT(receiver_map->has_dictionary_elements() ||
1719 // stub. There is no other way to determine the type of the external array 1698 receiver_map->has_fast_elements() ||
1720 // directly from the receiver type. 1699 receiver_map->has_fast_double_elements() ||
1721 Code::Kind kind = this->kind(); 1700 receiver_map->has_external_array_elements());
1722 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
1723 NORMAL,
1724 strict_mode);
1725 String* monomorphic_name = GetStubNameForCache(MONOMORPHIC);
1726 Object* maybe_default_stub = receiver_map->FindInCodeCache(monomorphic_name,
1727 flags);
1728 if (maybe_default_stub->IsUndefined()) {
1729 return generic_stub;
1730 }
1731 Code* default_stub = Code::cast(maybe_default_stub);
1732 return GetExternalArrayStubWithoutMapCheck(
1733 default_stub->external_array_type());
1734 } else if (receiver_map->has_fast_elements()) {
1735 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 1701 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1736 return GetFastElementStubWithoutMapCheck(is_js_array); 1702 return GetElementStubWithoutMapCheck(is_js_array,
1737 } else { 1703 receiver_map->elements_kind());
1738 return generic_stub;
1739 } 1704 }
1740 } 1705 }
1741 1706
1742 1707
1743 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver, 1708 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
1744 bool is_store, 1709 bool is_store,
1745 StrictModeFlag strict_mode, 1710 StrictModeFlag strict_mode,
1746 Code* generic_stub) { 1711 Code* generic_stub) {
1747 Code* result = NULL; 1712 Code* result = NULL;
1748 if (receiver->HasExternalArrayElements()) { 1713 if (receiver->HasFastElements() ||
1714 receiver->HasExternalArrayElements() ||
1715 receiver->HasFastDoubleElements() ||
1716 receiver->HasDictionaryElements()) {
1749 MaybeObject* maybe_stub = 1717 MaybeObject* maybe_stub =
1750 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( 1718 isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
1751 receiver, is_store, strict_mode);
1752 if (!maybe_stub->To(&result)) return maybe_stub;
1753 } else if (receiver->map()->has_fast_elements()) {
1754 MaybeObject* maybe_stub =
1755 isolate()->stub_cache()->ComputeKeyedLoadOrStoreFastElement(
1756 receiver, is_store, strict_mode); 1719 receiver, is_store, strict_mode);
1757 if (!maybe_stub->To(&result)) return maybe_stub; 1720 if (!maybe_stub->To(&result)) return maybe_stub;
1758 } else { 1721 } else {
1759 result = generic_stub; 1722 result = generic_stub;
1760 } 1723 }
1761 return result; 1724 return result;
1762 } 1725 }
1763 1726
1764 1727
1765 String* KeyedStoreIC::GetStubNameForCache(IC::State ic_state) { 1728 MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck(
1766 if (ic_state == MONOMORPHIC) { 1729 bool is_js_array,
1767 return isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol(); 1730 JSObject::ElementsKind elements_kind) {
1768 } else { 1731 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
1769 ASSERT(ic_state == MEGAMORPHIC);
1770 return isolate()->heap()->KeyedStoreSpecializedPolymorphic_symbol();
1771 }
1772 }
1773
1774
1775 MaybeObject* KeyedStoreIC::GetFastElementStubWithoutMapCheck(
1776 bool is_js_array) {
1777 return KeyedStoreFastElementStub(is_js_array).TryGetCode();
1778 }
1779
1780
1781 MaybeObject* KeyedStoreIC::GetExternalArrayStubWithoutMapCheck(
1782 ExternalArrayType array_type) {
1783 return KeyedStoreExternalArrayStub(array_type).TryGetCode();
1784 } 1732 }
1785 1733
1786 1734
1787 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub( 1735 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub(
1788 MapList* receiver_maps, 1736 MapList* receiver_maps,
1789 CodeList* targets, 1737 CodeList* targets,
1790 StrictModeFlag strict_mode) { 1738 StrictModeFlag strict_mode) {
1791 Object* object; 1739 Object* object;
1792 KeyedStoreStubCompiler compiler(strict_mode); 1740 KeyedStoreStubCompiler compiler(strict_mode);
1793 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps, 1741 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 1792
1845 // Do not use ICs for objects that require access checks (including 1793 // Do not use ICs for objects that require access checks (including
1846 // the global object). 1794 // the global object).
1847 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1795 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1848 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1796 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1849 1797
1850 if (use_ic) { 1798 if (use_ic) {
1851 Code* stub = (strict_mode == kStrictMode) 1799 Code* stub = (strict_mode == kStrictMode)
1852 ? generic_stub_strict() 1800 ? generic_stub_strict()
1853 : generic_stub(); 1801 : generic_stub();
1854 if (!force_generic) { 1802 if (object->IsJSObject()) {
1855 if (object->IsJSObject() && key->IsSmi()) { 1803 JSObject* receiver = JSObject::cast(*object);
1856 JSObject* receiver = JSObject::cast(*object); 1804 Heap* heap = Handle<JSObject>::cast(object)->GetHeap();
1857 MaybeObject* maybe_stub = ComputeStub(receiver, 1805 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map();
1858 true, 1806 if (elements_map == heap->non_strict_arguments_elements_map()) {
1859 strict_mode, 1807 stub = non_strict_arguments_stub();
1860 stub); 1808 } else if (!force_generic) {
1861 stub = maybe_stub->IsFailure() ? 1809 if (key->IsSmi() && (target() != non_strict_arguments_stub())) {
1862 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); 1810 HandleScope scope(isolate());
1811 MaybeObject* maybe_stub = ComputeStub(receiver,
1812 true,
1813 strict_mode,
1814 stub);
1815 stub = maybe_stub->IsFailure() ?
1816 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1817 }
1863 } 1818 }
1864 } 1819 }
1865 if (stub != NULL) set_target(stub); 1820 if (stub != NULL) set_target(stub);
1866 } 1821 }
1867 1822
1868 #ifdef DEBUG 1823 #ifdef DEBUG
1869 TraceIC("KeyedStoreIC", key, state, target()); 1824 TraceIC("KeyedStoreIC", key, state, target());
1870 #endif 1825 #endif
1871 1826
1872 // Set the property. 1827 // Set the property.
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2318 } 2273 }
2319 2274
2320 // Check for oddball objects. 2275 // Check for oddball objects.
2321 if (left->IsUndefined() && right->IsNumber()) return ODDBALL; 2276 if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
2322 if (left->IsNumber() && right->IsUndefined()) return ODDBALL; 2277 if (left->IsNumber() && right->IsUndefined()) return ODDBALL;
2323 2278
2324 return GENERIC; 2279 return GENERIC;
2325 } 2280 }
2326 2281
2327 2282
2328 // defined in code-stubs-<arch>.cc
2329 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
2330 Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info);
2331
2332
2333 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) { 2283 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) {
2334 ASSERT(args.length() == 4); 2284 ASSERT(args.length() == 4);
2335 2285
2336 HandleScope scope(isolate); 2286 HandleScope scope(isolate);
2337 Handle<Object> operand = args.at<Object>(0); 2287 Handle<Object> operand = args.at<Object>(0);
2338 int key = Smi::cast(args[1])->value(); 2288 Token::Value op = static_cast<Token::Value>(args.smi_at(1));
2339 Token::Value op = static_cast<Token::Value>(Smi::cast(args[2])->value()); 2289 UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2));
2340 UnaryOpIC::TypeInfo previous_type = 2290 UnaryOpIC::TypeInfo previous_type =
2341 static_cast<UnaryOpIC::TypeInfo>(Smi::cast(args[3])->value()); 2291 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3));
2342 2292
2343 UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand); 2293 UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand);
2344 type = UnaryOpIC::ComputeNewType(type, previous_type); 2294 type = UnaryOpIC::ComputeNewType(type, previous_type);
2345 2295
2346 Handle<Code> code = GetUnaryOpStub(key, type); 2296 UnaryOpStub stub(op, mode, type);
2297 Handle<Code> code = stub.GetCode();
2347 if (!code.is_null()) { 2298 if (!code.is_null()) {
2348 if (FLAG_trace_ic) { 2299 if (FLAG_trace_ic) {
2349 PrintF("[UnaryOpIC (%s->%s)#%s]\n", 2300 PrintF("[UnaryOpIC (%s->%s)#%s]\n",
2350 UnaryOpIC::GetName(previous_type), 2301 UnaryOpIC::GetName(previous_type),
2351 UnaryOpIC::GetName(type), 2302 UnaryOpIC::GetName(type),
2352 Token::Name(op)); 2303 Token::Name(op));
2353 } 2304 }
2354 UnaryOpIC ic(isolate); 2305 UnaryOpIC ic(isolate);
2355 ic.patch(*code); 2306 ic.patch(*code);
2356 } 2307 }
(...skipping 16 matching lines...) Expand all
2373 2324
2374 bool caught_exception; 2325 bool caught_exception;
2375 Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL, 2326 Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL,
2376 &caught_exception); 2327 &caught_exception);
2377 if (caught_exception) { 2328 if (caught_exception) {
2378 return Failure::Exception(); 2329 return Failure::Exception();
2379 } 2330 }
2380 return *result; 2331 return *result;
2381 } 2332 }
2382 2333
2383 // defined in code-stubs-<arch>.cc
2384 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
2385 Handle<Code> GetBinaryOpStub(int key,
2386 BinaryOpIC::TypeInfo type_info,
2387 BinaryOpIC::TypeInfo result_type);
2388
2389
2390 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) { 2334 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2391 ASSERT(args.length() == 5); 2335 ASSERT(args.length() == 5);
2392 2336
2393 HandleScope scope(isolate); 2337 HandleScope scope(isolate);
2394 Handle<Object> left = args.at<Object>(0); 2338 Handle<Object> left = args.at<Object>(0);
2395 Handle<Object> right = args.at<Object>(1); 2339 Handle<Object> right = args.at<Object>(1);
2396 int key = Smi::cast(args[2])->value(); 2340 int key = args.smi_at(2);
2397 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); 2341 Token::Value op = static_cast<Token::Value>(args.smi_at(3));
2398 BinaryOpIC::TypeInfo previous_type = 2342 BinaryOpIC::TypeInfo previous_type =
2399 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); 2343 static_cast<BinaryOpIC::TypeInfo>(args.smi_at(4));
2400 2344
2401 BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right); 2345 BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right);
2402 type = BinaryOpIC::JoinTypes(type, previous_type); 2346 type = BinaryOpIC::JoinTypes(type, previous_type);
2403 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED; 2347 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
2404 if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) && 2348 if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) &&
2405 op != Token::ADD) { 2349 op != Token::ADD) {
2406 type = BinaryOpIC::GENERIC; 2350 type = BinaryOpIC::GENERIC;
2407 } 2351 }
2408 if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) { 2352 if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) {
2409 if (op == Token::DIV || 2353 if (op == Token::DIV ||
2410 op == Token::MUL || 2354 op == Token::MUL ||
2411 op == Token::SHR || 2355 op == Token::SHR ||
2412 kSmiValueSize == 32) { 2356 kSmiValueSize == 32) {
2413 // Arithmetic on two Smi inputs has yielded a heap number. 2357 // Arithmetic on two Smi inputs has yielded a heap number.
2414 // That is the only way to get here from the Smi stub. 2358 // That is the only way to get here from the Smi stub.
2415 // With 32-bit Smis, all overflows give heap numbers, but with 2359 // With 32-bit Smis, all overflows give heap numbers, but with
2416 // 31-bit Smis, most operations overflow to int32 results. 2360 // 31-bit Smis, most operations overflow to int32 results.
2417 result_type = BinaryOpIC::HEAP_NUMBER; 2361 result_type = BinaryOpIC::HEAP_NUMBER;
2418 } else { 2362 } else {
2419 // Other operations on SMIs that overflow yield int32s. 2363 // Other operations on SMIs that overflow yield int32s.
2420 result_type = BinaryOpIC::INT32; 2364 result_type = BinaryOpIC::INT32;
2421 } 2365 }
2422 } 2366 }
2423 if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) { 2367 if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) {
2424 // We must be here because an operation on two INT32 types overflowed. 2368 // We must be here because an operation on two INT32 types overflowed.
2425 result_type = BinaryOpIC::HEAP_NUMBER; 2369 result_type = BinaryOpIC::HEAP_NUMBER;
2426 } 2370 }
2427 2371
2428 Handle<Code> code = GetBinaryOpStub(key, type, result_type); 2372 BinaryOpStub stub(key, type, result_type);
2373 Handle<Code> code = stub.GetCode();
2429 if (!code.is_null()) { 2374 if (!code.is_null()) {
2430 if (FLAG_trace_ic) { 2375 if (FLAG_trace_ic) {
2431 PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n", 2376 PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n",
2432 BinaryOpIC::GetName(previous_type), 2377 BinaryOpIC::GetName(previous_type),
2433 BinaryOpIC::GetName(type), 2378 BinaryOpIC::GetName(type),
2434 BinaryOpIC::GetName(result_type), 2379 BinaryOpIC::GetName(result_type),
2435 Token::Name(op)); 2380 Token::Name(op));
2436 } 2381 }
2437 BinaryOpIC ic(isolate); 2382 BinaryOpIC ic(isolate);
2438 ic.patch(*code); 2383 ic.patch(*code);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2548 if (state == UNINITIALIZED && 2493 if (state == UNINITIALIZED &&
2549 x->IsJSObject() && y->IsJSObject()) return OBJECTS; 2494 x->IsJSObject() && y->IsJSObject()) return OBJECTS;
2550 return GENERIC; 2495 return GENERIC;
2551 } 2496 }
2552 2497
2553 2498
2554 // Used from ic_<arch>.cc. 2499 // Used from ic_<arch>.cc.
2555 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2500 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2556 NoHandleAllocation na; 2501 NoHandleAllocation na;
2557 ASSERT(args.length() == 3); 2502 ASSERT(args.length() == 3);
2558 CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value())); 2503 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2559 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2504 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2560 return ic.target(); 2505 return ic.target();
2561 } 2506 }
2562 2507
2563 2508
2564 static const Address IC_utilities[] = { 2509 static const Address IC_utilities[] = {
2565 #define ADDR(name) FUNCTION_ADDR(name), 2510 #define ADDR(name) FUNCTION_ADDR(name),
2566 IC_UTIL_LIST(ADDR) 2511 IC_UTIL_LIST(ADDR)
2567 NULL 2512 NULL
2568 #undef ADDR 2513 #undef ADDR
2569 }; 2514 };
2570 2515
2571 2516
2572 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2517 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2573 return IC_utilities[id]; 2518 return IC_utilities[id];
2574 } 2519 }
2575 2520
2576 2521
2577 } } // namespace v8::internal 2522 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/incremental-marking.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698