| OLD | NEW |
| 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 22 matching lines...) Expand all Loading... |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "execution.h" | 34 #include "execution.h" |
| 35 #include "ic-inl.h" | 35 #include "ic-inl.h" |
| 36 #include "runtime.h" | 36 #include "runtime.h" |
| 37 #include "stub-cache.h" | 37 #include "stub-cache.h" |
| 38 | 38 |
| 39 namespace v8 { | 39 namespace v8 { |
| 40 namespace internal { | 40 namespace internal { |
| 41 | 41 |
| 42 #ifdef DEBUG | 42 #ifdef DEBUG |
| 43 static char TransitionMarkFromState(IC::State state) { | 43 char IC::TransitionMarkFromState(IC::State state) { |
| 44 switch (state) { | 44 switch (state) { |
| 45 case UNINITIALIZED: return '0'; | 45 case UNINITIALIZED: return '0'; |
| 46 case PREMONOMORPHIC: return 'P'; | 46 case PREMONOMORPHIC: return 'P'; |
| 47 case MONOMORPHIC: return '1'; | 47 case MONOMORPHIC: return '1'; |
| 48 case MONOMORPHIC_PROTOTYPE_FAILURE: return '^'; | 48 case MONOMORPHIC_PROTOTYPE_FAILURE: return '^'; |
| 49 case MEGAMORPHIC: return 'N'; | 49 case MEGAMORPHIC: return IsGeneric() ? 'G' : 'N'; |
| 50 | 50 |
| 51 // We never see the debugger states here, because the state is | 51 // We never see the debugger states here, because the state is |
| 52 // computed from the original code - not the patched code. Let | 52 // computed from the original code - not the patched code. Let |
| 53 // these cases fall through to the unreachable code below. | 53 // these cases fall through to the unreachable code below. |
| 54 case DEBUG_BREAK: break; | 54 case DEBUG_BREAK: break; |
| 55 case DEBUG_PREPARE_STEP_IN: break; | 55 case DEBUG_PREPARE_STEP_IN: break; |
| 56 } | 56 } |
| 57 UNREACHABLE(); | 57 UNREACHABLE(); |
| 58 return 0; | 58 return 0; |
| 59 } | 59 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 73 if (raw_frame->is_internal()) { | 73 if (raw_frame->is_internal()) { |
| 74 Isolate* isolate = new_target->GetIsolate(); | 74 Isolate* isolate = new_target->GetIsolate(); |
| 75 Code* apply_builtin = isolate->builtins()->builtin( | 75 Code* apply_builtin = isolate->builtins()->builtin( |
| 76 Builtins::kFunctionApply); | 76 Builtins::kFunctionApply); |
| 77 if (raw_frame->unchecked_code() == apply_builtin) { | 77 if (raw_frame->unchecked_code() == apply_builtin) { |
| 78 PrintF("apply from "); | 78 PrintF("apply from "); |
| 79 it.Advance(); | 79 it.Advance(); |
| 80 raw_frame = it.frame(); | 80 raw_frame = it.frame(); |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 if (raw_frame->is_java_script()) { | 83 JavaScriptFrame::PrintTop(stdout, false, true); |
| 84 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); | |
| 85 Code* js_code = frame->unchecked_code(); | |
| 86 // Find the function on the stack and both the active code for the | |
| 87 // function and the original code. | |
| 88 JSFunction* function = JSFunction::cast(frame->function()); | |
| 89 function->PrintName(); | |
| 90 int code_offset = | |
| 91 static_cast<int>(address() - js_code->instruction_start()); | |
| 92 PrintF("+%d", code_offset); | |
| 93 } else { | |
| 94 PrintF("<unknown>"); | |
| 95 } | |
| 96 PrintF(" (%c->%c)", | 84 PrintF(" (%c->%c)", |
| 97 TransitionMarkFromState(old_state), | 85 TransitionMarkFromState(old_state), |
| 98 TransitionMarkFromState(new_state)); | 86 TransitionMarkFromState(new_state)); |
| 99 name->Print(); | 87 name->Print(); |
| 100 PrintF("]\n"); | 88 PrintF("]\n"); |
| 101 } | 89 } |
| 102 } | 90 } |
| 91 |
| 92 #define TRACE_GENERIC_IC(type, reason) \ |
| 93 do { \ |
| 94 if (FLAG_trace_ic) { \ |
| 95 PrintF("[%s patching generic stub in ", type); \ |
| 96 JavaScriptFrame::PrintTop(stdout, false, true); \ |
| 97 PrintF(" (%s)]\n", reason); \ |
| 98 } \ |
| 99 } while (false) |
| 100 |
| 101 #else |
| 102 #define TRACE_GENERIC_IC(type, reason) |
| 103 #endif // DEBUG | 103 #endif // DEBUG |
| 104 | 104 |
| 105 | |
| 106 #define TRACE_IC(type, name, old_state, new_target) \ | 105 #define TRACE_IC(type, name, old_state, new_target) \ |
| 107 ASSERT((TraceIC(type, name, old_state, new_target), true)) | 106 ASSERT((TraceIC(type, name, old_state, new_target), true)) |
| 108 | 107 |
| 109 | |
| 110 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 108 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
| 111 ASSERT(isolate == Isolate::Current()); | 109 ASSERT(isolate == Isolate::Current()); |
| 112 // To improve the performance of the (much used) IC code, we unfold | 110 // To improve the performance of the (much used) IC code, we unfold |
| 113 // a few levels of the stack frame iteration code. This yields a | 111 // a few levels of the stack frame iteration code. This yields a |
| 114 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. | 112 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. |
| 115 const Address entry = | 113 const Address entry = |
| 116 Isolate::c_entry_fp(isolate->thread_local_top()); | 114 Isolate::c_entry_fp(isolate->thread_local_top()); |
| 117 Address* pc_address = | 115 Address* pc_address = |
| 118 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 116 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
| 119 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 117 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 130 for (int i = 0; i < depth + 1; i++) it.Advance(); | 128 for (int i = 0; i < depth + 1; i++) it.Advance(); |
| 131 StackFrame* frame = it.frame(); | 129 StackFrame* frame = it.frame(); |
| 132 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 130 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
| 133 #endif | 131 #endif |
| 134 fp_ = fp; | 132 fp_ = fp; |
| 135 pc_address_ = pc_address; | 133 pc_address_ = pc_address; |
| 136 } | 134 } |
| 137 | 135 |
| 138 | 136 |
| 139 #ifdef ENABLE_DEBUGGER_SUPPORT | 137 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 140 Address IC::OriginalCodeAddress() { | 138 Address IC::OriginalCodeAddress() const { |
| 141 HandleScope scope; | 139 HandleScope scope; |
| 142 // Compute the JavaScript frame for the frame pointer of this IC | 140 // Compute the JavaScript frame for the frame pointer of this IC |
| 143 // structure. We need this to be able to find the function | 141 // structure. We need this to be able to find the function |
| 144 // corresponding to the frame. | 142 // corresponding to the frame. |
| 145 StackFrameIterator it; | 143 StackFrameIterator it; |
| 146 while (it.frame()->fp() != this->fp()) it.Advance(); | 144 while (it.frame()->fp() != this->fp()) it.Advance(); |
| 147 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); | 145 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); |
| 148 // Find the function on the stack and both the active code for the | 146 // Find the function on the stack and both the active code for the |
| 149 // function and the original code. | 147 // function and the original code. |
| 150 JSFunction* function = JSFunction::cast(frame->function()); | 148 JSFunction* function = JSFunction::cast(frame->function()); |
| (...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1114 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1117 if (receiver->elements()->map() == | 1115 if (receiver->elements()->map() == |
| 1118 isolate()->heap()->non_strict_arguments_elements_map()) { | 1116 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1119 stub = non_strict_arguments_stub(); | 1117 stub = non_strict_arguments_stub(); |
| 1120 } else if (receiver->HasIndexedInterceptor()) { | 1118 } else if (receiver->HasIndexedInterceptor()) { |
| 1121 stub = indexed_interceptor_stub(); | 1119 stub = indexed_interceptor_stub(); |
| 1122 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1120 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
| 1123 stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub); | 1121 stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub); |
| 1124 } | 1122 } |
| 1125 } | 1123 } |
| 1124 } else { |
| 1125 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); |
| 1126 } | 1126 } |
| 1127 if (!stub.is_null()) set_target(*stub); | 1127 if (!stub.is_null()) set_target(*stub); |
| 1128 } | 1128 } |
| 1129 | 1129 |
| 1130 TRACE_IC("KeyedLoadIC", key, state, target()); | 1130 TRACE_IC("KeyedLoadIC", key, state, target()); |
| 1131 | 1131 |
| 1132 // Get the property. | 1132 // Get the property. |
| 1133 return Runtime::GetObjectProperty(isolate(), object, key); | 1133 return Runtime::GetObjectProperty(isolate(), object, key); |
| 1134 } | 1134 } |
| 1135 | 1135 |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1466 !IsTransitionStubKind(stub_kind)) { | 1466 !IsTransitionStubKind(stub_kind)) { |
| 1467 return ComputeMonomorphicStub( | 1467 return ComputeMonomorphicStub( |
| 1468 receiver, stub_kind, strict_mode, generic_stub); | 1468 receiver, stub_kind, strict_mode, generic_stub); |
| 1469 } | 1469 } |
| 1470 ASSERT(target() != *generic_stub); | 1470 ASSERT(target() != *generic_stub); |
| 1471 | 1471 |
| 1472 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1472 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
| 1473 // via megamorphic stubs, since they don't have a map in their relocation info | 1473 // via megamorphic stubs, since they don't have a map in their relocation info |
| 1474 // and so the stubs can't be harvested for the object needed for a map check. | 1474 // and so the stubs can't be harvested for the object needed for a map check. |
| 1475 if (target()->type() != NORMAL) { | 1475 if (target()->type() != NORMAL) { |
| 1476 TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type"); |
| 1476 return generic_stub; | 1477 return generic_stub; |
| 1477 } | 1478 } |
| 1478 | 1479 |
| 1479 // Determine the list of receiver maps that this call site has seen, | 1480 // Determine the list of receiver maps that this call site has seen, |
| 1480 // adding the map that was just encountered. | 1481 // adding the map that was just encountered. |
| 1481 MapHandleList target_receiver_maps; | 1482 MapHandleList target_receiver_maps; |
| 1482 Handle<Map> receiver_map(receiver->map()); | 1483 Handle<Map> receiver_map(receiver->map()); |
| 1483 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1484 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
| 1484 target_receiver_maps.Add(receiver_map); | 1485 target_receiver_maps.Add(receiver_map); |
| 1485 } else { | 1486 } else { |
| 1486 GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps); | 1487 GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps); |
| 1487 } | 1488 } |
| 1488 bool map_added = | 1489 bool map_added = |
| 1489 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1490 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
| 1490 if (IsTransitionStubKind(stub_kind)) { | 1491 if (IsTransitionStubKind(stub_kind)) { |
| 1491 Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind); | 1492 Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind); |
| 1492 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map); | 1493 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map); |
| 1493 } | 1494 } |
| 1494 if (!map_added) { | 1495 if (!map_added) { |
| 1495 // If the miss wasn't due to an unseen map, a polymorphic stub | 1496 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1496 // won't help, use the generic stub. | 1497 // won't help, use the generic stub. |
| 1498 TRACE_GENERIC_IC("KeyedIC", "same map added twice"); |
| 1497 return generic_stub; | 1499 return generic_stub; |
| 1498 } | 1500 } |
| 1499 | 1501 |
| 1500 // If the maximum number of receiver maps has been exceeded, use the generic | 1502 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1501 // version of the IC. | 1503 // version of the IC. |
| 1502 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1504 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1505 TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded"); |
| 1503 return generic_stub; | 1506 return generic_stub; |
| 1504 } | 1507 } |
| 1505 | 1508 |
| 1506 Handle<PolymorphicCodeCache> cache = | 1509 Handle<PolymorphicCodeCache> cache = |
| 1507 isolate()->factory()->polymorphic_code_cache(); | 1510 isolate()->factory()->polymorphic_code_cache(); |
| 1508 Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, strict_mode); | 1511 Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, strict_mode); |
| 1509 Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags); | 1512 Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags); |
| 1510 if (probe->IsCode()) return Handle<Code>::cast(probe); | 1513 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 1511 | 1514 |
| 1512 Handle<Code> stub = | 1515 Handle<Code> stub = |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1678 } else if (value->IsHeapObject()) { | 1681 } else if (value->IsHeapObject()) { |
| 1679 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT; | 1682 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT; |
| 1680 } | 1683 } |
| 1681 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) { | 1684 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) { |
| 1682 if (!value->IsSmi() && !value->IsHeapNumber()) { | 1685 if (!value->IsSmi() && !value->IsHeapNumber()) { |
| 1683 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT; | 1686 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT; |
| 1684 } | 1687 } |
| 1685 } | 1688 } |
| 1686 stub = ComputeStub(receiver, stub_kind, strict_mode, stub); | 1689 stub = ComputeStub(receiver, stub_kind, strict_mode, stub); |
| 1687 } | 1690 } |
| 1691 } else { |
| 1692 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); |
| 1688 } | 1693 } |
| 1689 } | 1694 } |
| 1690 if (!stub.is_null()) set_target(*stub); | 1695 if (!stub.is_null()) set_target(*stub); |
| 1691 } | 1696 } |
| 1692 | 1697 |
| 1693 TRACE_IC("KeyedStoreIC", key, state, target()); | 1698 TRACE_IC("KeyedStoreIC", key, state, target()); |
| 1694 | 1699 |
| 1695 // Set the property. | 1700 // Set the property. |
| 1696 return Runtime::SetObjectProperty( | 1701 return Runtime::SetObjectProperty( |
| 1697 isolate(), object , key, value, NONE, strict_mode); | 1702 isolate(), object , key, value, NONE, strict_mode); |
| (...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2388 #undef ADDR | 2393 #undef ADDR |
| 2389 }; | 2394 }; |
| 2390 | 2395 |
| 2391 | 2396 |
| 2392 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2397 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2393 return IC_utilities[id]; | 2398 return IC_utilities[id]; |
| 2394 } | 2399 } |
| 2395 | 2400 |
| 2396 | 2401 |
| 2397 } } // namespace v8::internal | 2402 } } // namespace v8::internal |
| OLD | NEW |