| 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 |