OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 // string wrapper objects. The length property of string wrapper | 815 // string wrapper objects. The length property of string wrapper |
816 // objects is read-only and therefore always returns the length of | 816 // objects is read-only and therefore always returns the length of |
817 // the underlying string value. See ECMA-262 15.5.5.1. | 817 // the underlying string value. See ECMA-262 15.5.5.1. |
818 if ((object->IsString() || object->IsStringWrapper()) && | 818 if ((object->IsString() || object->IsStringWrapper()) && |
819 name->Equals(isolate()->heap()->length_symbol())) { | 819 name->Equals(isolate()->heap()->length_symbol())) { |
820 Handle<Code> stub; | 820 Handle<Code> stub; |
821 if (state == UNINITIALIZED) { | 821 if (state == UNINITIALIZED) { |
822 stub = pre_monomorphic_stub(); | 822 stub = pre_monomorphic_stub(); |
823 } else if (state == PREMONOMORPHIC) { | 823 } else if (state == PREMONOMORPHIC) { |
824 StringLengthStub string_length_stub(kind(), !object->IsString()); | 824 StringLengthStub string_length_stub(kind(), !object->IsString()); |
825 stub = string_length_stub.GetCode(); | 825 stub = string_length_stub.GetCode(isolate()); |
826 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | 826 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { |
827 StringLengthStub string_length_stub(kind(), true); | 827 StringLengthStub string_length_stub(kind(), true); |
828 stub = string_length_stub.GetCode(); | 828 stub = string_length_stub.GetCode(isolate()); |
829 } else if (state != MEGAMORPHIC) { | 829 } else if (state != MEGAMORPHIC) { |
830 ASSERT(state != GENERIC); | 830 ASSERT(state != GENERIC); |
831 stub = megamorphic_stub(); | 831 stub = megamorphic_stub(); |
832 } | 832 } |
833 if (!stub.is_null()) { | 833 if (!stub.is_null()) { |
834 set_target(*stub); | 834 set_target(*stub); |
835 #ifdef DEBUG | 835 #ifdef DEBUG |
836 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 836 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
837 #endif | 837 #endif |
838 } | 838 } |
839 // Get the string if we have a string wrapper object. | 839 // Get the string if we have a string wrapper object. |
840 Handle<Object> string = object->IsJSValue() | 840 Handle<Object> string = object->IsJSValue() |
841 ? Handle<Object>(Handle<JSValue>::cast(object)->value(), isolate()) | 841 ? Handle<Object>(Handle<JSValue>::cast(object)->value(), isolate()) |
842 : object; | 842 : object; |
843 return Smi::FromInt(String::cast(*string)->length()); | 843 return Smi::FromInt(String::cast(*string)->length()); |
844 } | 844 } |
845 | 845 |
846 // Use specialized code for getting the length of arrays. | 846 // Use specialized code for getting the length of arrays. |
847 if (object->IsJSArray() && | 847 if (object->IsJSArray() && |
848 name->Equals(isolate()->heap()->length_symbol())) { | 848 name->Equals(isolate()->heap()->length_symbol())) { |
849 Handle<Code> stub; | 849 Handle<Code> stub; |
850 if (state == UNINITIALIZED) { | 850 if (state == UNINITIALIZED) { |
851 stub = pre_monomorphic_stub(); | 851 stub = pre_monomorphic_stub(); |
852 } else if (state == PREMONOMORPHIC) { | 852 } else if (state == PREMONOMORPHIC) { |
853 ArrayLengthStub array_length_stub(kind()); | 853 ArrayLengthStub array_length_stub(kind()); |
854 stub = array_length_stub.GetCode(); | 854 stub = array_length_stub.GetCode(isolate()); |
855 } else if (state != MEGAMORPHIC) { | 855 } else if (state != MEGAMORPHIC) { |
856 ASSERT(state != GENERIC); | 856 ASSERT(state != GENERIC); |
857 stub = megamorphic_stub(); | 857 stub = megamorphic_stub(); |
858 } | 858 } |
859 if (!stub.is_null()) { | 859 if (!stub.is_null()) { |
860 set_target(*stub); | 860 set_target(*stub); |
861 #ifdef DEBUG | 861 #ifdef DEBUG |
862 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 862 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); |
863 #endif | 863 #endif |
864 } | 864 } |
865 return JSArray::cast(*object)->length(); | 865 return JSArray::cast(*object)->length(); |
866 } | 866 } |
867 | 867 |
868 // Use specialized code for getting prototype of functions. | 868 // Use specialized code for getting prototype of functions. |
869 if (object->IsJSFunction() && | 869 if (object->IsJSFunction() && |
870 name->Equals(isolate()->heap()->prototype_symbol()) && | 870 name->Equals(isolate()->heap()->prototype_symbol()) && |
871 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 871 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
872 Handle<Code> stub; | 872 Handle<Code> stub; |
873 if (state == UNINITIALIZED) { | 873 if (state == UNINITIALIZED) { |
874 stub = pre_monomorphic_stub(); | 874 stub = pre_monomorphic_stub(); |
875 } else if (state == PREMONOMORPHIC) { | 875 } else if (state == PREMONOMORPHIC) { |
876 FunctionPrototypeStub function_prototype_stub(kind()); | 876 FunctionPrototypeStub function_prototype_stub(kind()); |
877 stub = function_prototype_stub.GetCode(); | 877 stub = function_prototype_stub.GetCode(isolate()); |
878 } else if (state != MEGAMORPHIC) { | 878 } else if (state != MEGAMORPHIC) { |
879 ASSERT(state != GENERIC); | 879 ASSERT(state != GENERIC); |
880 stub = megamorphic_stub(); | 880 stub = megamorphic_stub(); |
881 } | 881 } |
882 if (!stub.is_null()) { | 882 if (!stub.is_null()) { |
883 set_target(*stub); | 883 set_target(*stub); |
884 #ifdef DEBUG | 884 #ifdef DEBUG |
885 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 885 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
886 #endif | 886 #endif |
887 } | 887 } |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 } | 1391 } |
1392 | 1392 |
1393 // Use specialized code for setting the length of arrays with fast | 1393 // Use specialized code for setting the length of arrays with fast |
1394 // properties. Slow properties might indicate redefinition of the length | 1394 // properties. Slow properties might indicate redefinition of the length |
1395 // property. | 1395 // property. |
1396 if (FLAG_use_ic && | 1396 if (FLAG_use_ic && |
1397 receiver->IsJSArray() && | 1397 receiver->IsJSArray() && |
1398 name->Equals(isolate()->heap()->length_symbol()) && | 1398 name->Equals(isolate()->heap()->length_symbol()) && |
1399 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1399 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
1400 receiver->HasFastProperties()) { | 1400 receiver->HasFastProperties()) { |
1401 Handle<Code> stub = StoreArrayLengthStub(kind(), strict_mode).GetCode(); | 1401 Handle<Code> stub = |
| 1402 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); |
1402 set_target(*stub); | 1403 set_target(*stub); |
1403 TRACE_IC("StoreIC", name, state, *stub); | 1404 TRACE_IC("StoreIC", name, state, *stub); |
1404 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1405 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
1405 } | 1406 } |
1406 | 1407 |
1407 if (receiver->IsJSGlobalProxy()) { | 1408 if (receiver->IsJSGlobalProxy()) { |
1408 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { | 1409 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
1409 // Generate a generic stub that goes to the runtime when we see a global | 1410 // Generate a generic stub that goes to the runtime when we see a global |
1410 // proxy as receiver. | 1411 // proxy as receiver. |
1411 Handle<Code> stub = (strict_mode == kStrictMode) | 1412 Handle<Code> stub = (strict_mode == kStrictMode) |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2140 Handle<Object> operand = args.at<Object>(0); | 2141 Handle<Object> operand = args.at<Object>(0); |
2141 Token::Value op = static_cast<Token::Value>(args.smi_at(1)); | 2142 Token::Value op = static_cast<Token::Value>(args.smi_at(1)); |
2142 UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2)); | 2143 UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2)); |
2143 UnaryOpIC::TypeInfo previous_type = | 2144 UnaryOpIC::TypeInfo previous_type = |
2144 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); | 2145 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); |
2145 | 2146 |
2146 UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand); | 2147 UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand); |
2147 type = UnaryOpIC::ComputeNewType(type, previous_type); | 2148 type = UnaryOpIC::ComputeNewType(type, previous_type); |
2148 | 2149 |
2149 UnaryOpStub stub(op, mode, type); | 2150 UnaryOpStub stub(op, mode, type); |
2150 Handle<Code> code = stub.GetCode(); | 2151 Handle<Code> code = stub.GetCode(isolate); |
2151 if (!code.is_null()) { | 2152 if (!code.is_null()) { |
2152 if (FLAG_trace_ic) { | 2153 if (FLAG_trace_ic) { |
2153 PrintF("[UnaryOpIC in "); | 2154 PrintF("[UnaryOpIC in "); |
2154 JavaScriptFrame::PrintTop(isolate, stdout, false, true); | 2155 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
2155 PrintF(" (%s->%s)#%s @ %p]\n", | 2156 PrintF(" (%s->%s)#%s @ %p]\n", |
2156 UnaryOpIC::GetName(previous_type), | 2157 UnaryOpIC::GetName(previous_type), |
2157 UnaryOpIC::GetName(type), | 2158 UnaryOpIC::GetName(type), |
2158 Token::Name(op), | 2159 Token::Name(op), |
2159 static_cast<void*>(*code)); | 2160 static_cast<void*>(*code)); |
2160 } | 2161 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2268 } | 2269 } |
2269 } | 2270 } |
2270 if (new_overall == BinaryOpIC::INT32 && | 2271 if (new_overall == BinaryOpIC::INT32 && |
2271 previous_overall == BinaryOpIC::INT32) { | 2272 previous_overall == BinaryOpIC::INT32) { |
2272 if (new_left == previous_left && new_right == previous_right) { | 2273 if (new_left == previous_left && new_right == previous_right) { |
2273 result_type = BinaryOpIC::HEAP_NUMBER; | 2274 result_type = BinaryOpIC::HEAP_NUMBER; |
2274 } | 2275 } |
2275 } | 2276 } |
2276 | 2277 |
2277 BinaryOpStub stub(key, new_left, new_right, result_type); | 2278 BinaryOpStub stub(key, new_left, new_right, result_type); |
2278 Handle<Code> code = stub.GetCode(); | 2279 Handle<Code> code = stub.GetCode(isolate); |
2279 if (!code.is_null()) { | 2280 if (!code.is_null()) { |
2280 #ifdef DEBUG | 2281 #ifdef DEBUG |
2281 if (FLAG_trace_ic) { | 2282 if (FLAG_trace_ic) { |
2282 PrintF("[BinaryOpIC in "); | 2283 PrintF("[BinaryOpIC in "); |
2283 JavaScriptFrame::PrintTop(isolate, stdout, false, true); | 2284 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
2284 PrintF(" ((%s+%s)->((%s+%s)->%s))#%s @ %p]\n", | 2285 PrintF(" ((%s+%s)->((%s+%s)->%s))#%s @ %p]\n", |
2285 BinaryOpIC::GetName(previous_left), | 2286 BinaryOpIC::GetName(previous_left), |
2286 BinaryOpIC::GetName(previous_right), | 2287 BinaryOpIC::GetName(previous_right), |
2287 BinaryOpIC::GetName(new_left), | 2288 BinaryOpIC::GetName(new_left), |
2288 BinaryOpIC::GetName(new_right), | 2289 BinaryOpIC::GetName(new_right), |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2358 | 2359 |
2359 | 2360 |
2360 Code* CompareIC::GetRawUninitialized(Token::Value op) { | 2361 Code* CompareIC::GetRawUninitialized(Token::Value op) { |
2361 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2362 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
2362 Code* code = NULL; | 2363 Code* code = NULL; |
2363 CHECK(stub.FindCodeInCache(&code, Isolate::Current())); | 2364 CHECK(stub.FindCodeInCache(&code, Isolate::Current())); |
2364 return code; | 2365 return code; |
2365 } | 2366 } |
2366 | 2367 |
2367 | 2368 |
2368 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { | 2369 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { |
2369 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2370 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
2370 return stub.GetCode(); | 2371 return stub.GetCode(isolate); |
2371 } | 2372 } |
2372 | 2373 |
2373 | 2374 |
2374 const char* CompareIC::GetStateName(State state) { | 2375 const char* CompareIC::GetStateName(State state) { |
2375 switch (state) { | 2376 switch (state) { |
2376 case UNINITIALIZED: return "UNINITIALIZED"; | 2377 case UNINITIALIZED: return "UNINITIALIZED"; |
2377 case SMI: return "SMI"; | 2378 case SMI: return "SMI"; |
2378 case HEAP_NUMBER: return "HEAP_NUMBER"; | 2379 case HEAP_NUMBER: return "HEAP_NUMBER"; |
2379 case OBJECT: return "OBJECTS"; | 2380 case OBJECT: return "OBJECTS"; |
2380 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; | 2381 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2487 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2488 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
2488 &previous_right, &previous_state, NULL); | 2489 &previous_right, &previous_state, NULL); |
2489 State new_left = InputState(previous_left, x); | 2490 State new_left = InputState(previous_left, x); |
2490 State new_right = InputState(previous_right, y); | 2491 State new_right = InputState(previous_right, y); |
2491 State state = TargetState(previous_state, previous_left, previous_right, | 2492 State state = TargetState(previous_state, previous_left, previous_right, |
2492 HasInlinedSmiCode(address()), x, y); | 2493 HasInlinedSmiCode(address()), x, y); |
2493 ICCompareStub stub(op_, new_left, new_right, state); | 2494 ICCompareStub stub(op_, new_left, new_right, state); |
2494 if (state == KNOWN_OBJECTS) { | 2495 if (state == KNOWN_OBJECTS) { |
2495 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); | 2496 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); |
2496 } | 2497 } |
2497 set_target(*stub.GetCode()); | 2498 set_target(*stub.GetCode(isolate())); |
2498 | 2499 |
2499 #ifdef DEBUG | 2500 #ifdef DEBUG |
2500 if (FLAG_trace_ic) { | 2501 if (FLAG_trace_ic) { |
2501 PrintF("[CompareIC in "); | 2502 PrintF("[CompareIC in "); |
2502 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2503 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
2503 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 2504 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
2504 GetStateName(previous_left), | 2505 GetStateName(previous_left), |
2505 GetStateName(previous_right), | 2506 GetStateName(previous_right), |
2506 GetStateName(previous_state), | 2507 GetStateName(previous_state), |
2507 GetStateName(new_left), | 2508 GetStateName(new_left), |
2508 GetStateName(new_right), | 2509 GetStateName(new_right), |
2509 GetStateName(state), | 2510 GetStateName(state), |
2510 Token::Name(op_), | 2511 Token::Name(op_), |
2511 static_cast<void*>(*stub.GetCode())); | 2512 static_cast<void*>(*stub.GetCode(isolate()))); |
2512 } | 2513 } |
2513 #endif | 2514 #endif |
2514 | 2515 |
2515 // Activate inlined smi code. | 2516 // Activate inlined smi code. |
2516 if (previous_state == UNINITIALIZED) { | 2517 if (previous_state == UNINITIALIZED) { |
2517 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2518 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
2518 } | 2519 } |
2519 } | 2520 } |
2520 | 2521 |
2521 | 2522 |
(...skipping 13 matching lines...) Expand all Loading... |
2535 HandleScope scope(isolate); | 2536 HandleScope scope(isolate); |
2536 Handle<Object> object = args.at<Object>(0); | 2537 Handle<Object> object = args.at<Object>(0); |
2537 Register tos = Register::from_code(args.smi_at(1)); | 2538 Register tos = Register::from_code(args.smi_at(1)); |
2538 ToBooleanStub::Types old_types(args.smi_at(2)); | 2539 ToBooleanStub::Types old_types(args.smi_at(2)); |
2539 | 2540 |
2540 ToBooleanStub::Types new_types(old_types); | 2541 ToBooleanStub::Types new_types(old_types); |
2541 bool to_boolean_value = new_types.Record(object); | 2542 bool to_boolean_value = new_types.Record(object); |
2542 old_types.TraceTransition(new_types); | 2543 old_types.TraceTransition(new_types); |
2543 | 2544 |
2544 ToBooleanStub stub(tos, new_types); | 2545 ToBooleanStub stub(tos, new_types); |
2545 Handle<Code> code = stub.GetCode(); | 2546 Handle<Code> code = stub.GetCode(isolate); |
2546 ToBooleanIC ic(isolate); | 2547 ToBooleanIC ic(isolate); |
2547 ic.patch(*code); | 2548 ic.patch(*code); |
2548 return Smi::FromInt(to_boolean_value ? 1 : 0); | 2549 return Smi::FromInt(to_boolean_value ? 1 : 0); |
2549 } | 2550 } |
2550 | 2551 |
2551 | 2552 |
2552 void ToBooleanIC::patch(Code* code) { | 2553 void ToBooleanIC::patch(Code* code) { |
2553 set_target(code); | 2554 set_target(code); |
2554 } | 2555 } |
2555 | 2556 |
2556 | 2557 |
2557 static const Address IC_utilities[] = { | 2558 static const Address IC_utilities[] = { |
2558 #define ADDR(name) FUNCTION_ADDR(name), | 2559 #define ADDR(name) FUNCTION_ADDR(name), |
2559 IC_UTIL_LIST(ADDR) | 2560 IC_UTIL_LIST(ADDR) |
2560 NULL | 2561 NULL |
2561 #undef ADDR | 2562 #undef ADDR |
2562 }; | 2563 }; |
2563 | 2564 |
2564 | 2565 |
2565 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2566 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2566 return IC_utilities[id]; | 2567 return IC_utilities[id]; |
2567 } | 2568 } |
2568 | 2569 |
2569 | 2570 |
2570 } } // namespace v8::internal | 2571 } } // namespace v8::internal |
OLD | NEW |