| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 } | 57 } |
| 58 UNREACHABLE(); | 58 UNREACHABLE(); |
| 59 return 0; | 59 return 0; |
| 60 } | 60 } |
| 61 | 61 |
| 62 void IC::TraceIC(const char* type, | 62 void IC::TraceIC(const char* type, |
| 63 Handle<Object> name, | 63 Handle<Object> name, |
| 64 State old_state, | 64 State old_state, |
| 65 Code* new_target) { | 65 Code* new_target) { |
| 66 if (FLAG_trace_ic) { | 66 if (FLAG_trace_ic) { |
| 67 State new_state = StateFrom(new_target, | 67 Object* undef = new_target->GetHeap()->undefined_value(); |
| 68 HEAP->undefined_value(), | 68 State new_state = StateFrom(new_target, undef, undef); |
| 69 HEAP->undefined_value()); | |
| 70 PrintF("[%s in ", type); | 69 PrintF("[%s in ", type); |
| 71 StackFrameIterator it; | 70 Isolate* isolate = new_target->GetIsolate(); |
| 71 StackFrameIterator it(isolate); |
| 72 while (it.frame()->fp() != this->fp()) it.Advance(); | 72 while (it.frame()->fp() != this->fp()) it.Advance(); |
| 73 StackFrame* raw_frame = it.frame(); | 73 StackFrame* raw_frame = it.frame(); |
| 74 if (raw_frame->is_internal()) { | 74 if (raw_frame->is_internal()) { |
| 75 Isolate* isolate = new_target->GetIsolate(); | |
| 76 Code* apply_builtin = isolate->builtins()->builtin( | 75 Code* apply_builtin = isolate->builtins()->builtin( |
| 77 Builtins::kFunctionApply); | 76 Builtins::kFunctionApply); |
| 78 if (raw_frame->unchecked_code() == apply_builtin) { | 77 if (raw_frame->unchecked_code() == apply_builtin) { |
| 79 PrintF("apply from "); | 78 PrintF("apply from "); |
| 80 it.Advance(); | 79 it.Advance(); |
| 81 raw_frame = it.frame(); | 80 raw_frame = it.frame(); |
| 82 } | 81 } |
| 83 } | 82 } |
| 84 JavaScriptFrame::PrintTop(stdout, false, true); | 83 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
| 85 bool new_can_grow = | 84 bool new_can_grow = |
| 86 Code::GetKeyedAccessGrowMode(new_target->extra_ic_state()) == | 85 Code::GetKeyedAccessGrowMode(new_target->extra_ic_state()) == |
| 87 ALLOW_JSARRAY_GROWTH; | 86 ALLOW_JSARRAY_GROWTH; |
| 88 PrintF(" (%c->%c%s)", | 87 PrintF(" (%c->%c%s)", |
| 89 TransitionMarkFromState(old_state), | 88 TransitionMarkFromState(old_state), |
| 90 TransitionMarkFromState(new_state), | 89 TransitionMarkFromState(new_state), |
| 91 new_can_grow ? ".GROW" : ""); | 90 new_can_grow ? ".GROW" : ""); |
| 92 name->Print(); | 91 name->Print(); |
| 93 PrintF("]\n"); | 92 PrintF("]\n"); |
| 94 } | 93 } |
| 95 } | 94 } |
| 96 | 95 |
| 97 #define TRACE_GENERIC_IC(type, reason) \ | 96 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
| 98 do { \ | 97 do { \ |
| 99 if (FLAG_trace_ic) { \ | 98 if (FLAG_trace_ic) { \ |
| 100 PrintF("[%s patching generic stub in ", type); \ | 99 PrintF("[%s patching generic stub in ", type); \ |
| 101 JavaScriptFrame::PrintTop(stdout, false, true); \ | 100 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ |
| 102 PrintF(" (%s)]\n", reason); \ | 101 PrintF(" (%s)]\n", reason); \ |
| 103 } \ | 102 } \ |
| 104 } while (false) | 103 } while (false) |
| 105 | 104 |
| 106 #else | 105 #else |
| 107 #define TRACE_GENERIC_IC(type, reason) | 106 #define TRACE_GENERIC_IC(isolate, type, reason) |
| 108 #endif // DEBUG | 107 #endif // DEBUG |
| 109 | 108 |
| 110 #define TRACE_IC(type, name, old_state, new_target) \ | 109 #define TRACE_IC(type, name, old_state, new_target) \ |
| 111 ASSERT((TraceIC(type, name, old_state, new_target), true)) | 110 ASSERT((TraceIC(type, name, old_state, new_target), true)) |
| 112 | 111 |
| 113 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 112 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
| 114 // To improve the performance of the (much used) IC code, we unfold a few | 113 // To improve the performance of the (much used) IC code, we unfold a few |
| 115 // levels of the stack frame iteration code. This yields a ~35% speedup when | 114 // levels of the stack frame iteration code. This yields a ~35% speedup when |
| 116 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 115 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
| 117 const Address entry = | 116 const Address entry = |
| 118 Isolate::c_entry_fp(isolate->thread_local_top()); | 117 Isolate::c_entry_fp(isolate->thread_local_top()); |
| 119 Address* pc_address = | 118 Address* pc_address = |
| 120 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 119 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
| 121 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 120 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
| 122 // If there's another JavaScript frame on the stack or a | 121 // If there's another JavaScript frame on the stack or a |
| 123 // StubFailureTrampoline, we need to look one frame further down the stack to | 122 // StubFailureTrampoline, we need to look one frame further down the stack to |
| 124 // find the frame pointer and the return address stack slot. | 123 // find the frame pointer and the return address stack slot. |
| 125 if (depth == EXTRA_CALL_FRAME) { | 124 if (depth == EXTRA_CALL_FRAME) { |
| 126 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 125 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; |
| 127 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 126 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); |
| 128 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 127 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); |
| 129 } | 128 } |
| 130 #ifdef DEBUG | 129 #ifdef DEBUG |
| 131 StackFrameIterator it; | 130 StackFrameIterator it(isolate); |
| 132 for (int i = 0; i < depth + 1; i++) it.Advance(); | 131 for (int i = 0; i < depth + 1; i++) it.Advance(); |
| 133 StackFrame* frame = it.frame(); | 132 StackFrame* frame = it.frame(); |
| 134 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 133 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
| 135 #endif | 134 #endif |
| 136 fp_ = fp; | 135 fp_ = fp; |
| 137 pc_address_ = pc_address; | 136 pc_address_ = pc_address; |
| 138 } | 137 } |
| 139 | 138 |
| 140 | 139 |
| 141 #ifdef ENABLE_DEBUGGER_SUPPORT | 140 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 142 Address IC::OriginalCodeAddress() const { | 141 Address IC::OriginalCodeAddress() const { |
| 143 HandleScope scope; | 142 HandleScope scope(isolate()); |
| 144 // Compute the JavaScript frame for the frame pointer of this IC | 143 // Compute the JavaScript frame for the frame pointer of this IC |
| 145 // structure. We need this to be able to find the function | 144 // structure. We need this to be able to find the function |
| 146 // corresponding to the frame. | 145 // corresponding to the frame. |
| 147 StackFrameIterator it; | 146 StackFrameIterator it(isolate()); |
| 148 while (it.frame()->fp() != this->fp()) it.Advance(); | 147 while (it.frame()->fp() != this->fp()) it.Advance(); |
| 149 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); | 148 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); |
| 150 // Find the function on the stack and both the active code for the | 149 // Find the function on the stack and both the active code for the |
| 151 // function and the original code. | 150 // function and the original code. |
| 152 JSFunction* function = JSFunction::cast(frame->function()); | 151 JSFunction* function = JSFunction::cast(frame->function()); |
| 153 Handle<SharedFunctionInfo> shared(function->shared()); | 152 Handle<SharedFunctionInfo> shared(function->shared()); |
| 154 Code* code = shared->code(); | 153 Code* code = shared->code(); |
| 155 ASSERT(Debug::HasDebugInfo(shared)); | 154 ASSERT(Debug::HasDebugInfo(shared)); |
| 156 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); | 155 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); |
| 157 ASSERT(original_code->IsCode()); | 156 ASSERT(original_code->IsCode()); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 } | 445 } |
| 447 | 446 |
| 448 | 447 |
| 449 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) { | 448 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) { |
| 450 Handle<Object> delegate = Execution::GetFunctionDelegate(object); | 449 Handle<Object> delegate = Execution::GetFunctionDelegate(object); |
| 451 | 450 |
| 452 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { | 451 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { |
| 453 // Patch the receiver and use the delegate as the function to | 452 // Patch the receiver and use the delegate as the function to |
| 454 // invoke. This is used for invoking objects as if they were functions. | 453 // invoke. This is used for invoking objects as if they were functions. |
| 455 const int argc = target()->arguments_count(); | 454 const int argc = target()->arguments_count(); |
| 456 StackFrameLocator locator; | 455 StackFrameLocator locator(isolate()); |
| 457 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 456 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| 458 int index = frame->ComputeExpressionsCount() - (argc + 1); | 457 int index = frame->ComputeExpressionsCount() - (argc + 1); |
| 459 frame->SetExpression(index, *object); | 458 frame->SetExpression(index, *object); |
| 460 } | 459 } |
| 461 | 460 |
| 462 return delegate; | 461 return delegate; |
| 463 } | 462 } |
| 464 | 463 |
| 465 | 464 |
| 466 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, | 465 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, |
| 467 Handle<Object> object) { | 466 Handle<Object> object) { |
| 468 while (callee->IsJSFunctionProxy()) { | 467 while (callee->IsJSFunctionProxy()) { |
| 469 callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap()); | 468 callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap()); |
| 470 } | 469 } |
| 471 | 470 |
| 472 if (callee->IsJSFunction()) { | 471 if (callee->IsJSFunction()) { |
| 473 Handle<JSFunction> function = Handle<JSFunction>::cast(callee); | 472 Handle<JSFunction> function = Handle<JSFunction>::cast(callee); |
| 474 if (!function->shared()->is_classic_mode() || function->IsBuiltin()) { | 473 if (!function->shared()->is_classic_mode() || function->IsBuiltin()) { |
| 475 // Do not wrap receiver for strict mode functions or for builtins. | 474 // Do not wrap receiver for strict mode functions or for builtins. |
| 476 return; | 475 return; |
| 477 } | 476 } |
| 478 } | 477 } |
| 479 | 478 |
| 480 // And only wrap string, number or boolean. | 479 // And only wrap string, number or boolean. |
| 481 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 480 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
| 482 // Change the receiver to the result of calling ToObject on it. | 481 // Change the receiver to the result of calling ToObject on it. |
| 483 const int argc = this->target()->arguments_count(); | 482 const int argc = this->target()->arguments_count(); |
| 484 StackFrameLocator locator; | 483 StackFrameLocator locator(isolate()); |
| 485 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 484 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| 486 int index = frame->ComputeExpressionsCount() - (argc + 1); | 485 int index = frame->ComputeExpressionsCount() - (argc + 1); |
| 487 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 486 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
| 488 } | 487 } |
| 489 } | 488 } |
| 490 | 489 |
| 491 | 490 |
| 492 MaybeObject* CallICBase::LoadFunction(State state, | 491 MaybeObject* CallICBase::LoadFunction(State state, |
| 493 Code::ExtraICState extra_ic_state, | 492 Code::ExtraICState extra_ic_state, |
| 494 Handle<Object> object, | 493 Handle<Object> object, |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 } | 1154 } |
| 1156 | 1155 |
| 1157 | 1156 |
| 1158 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { | 1157 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { |
| 1159 State ic_state = target()->ic_state(); | 1158 State ic_state = target()->ic_state(); |
| 1160 | 1159 |
| 1161 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1160 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
| 1162 // via megamorphic stubs, since they don't have a map in their relocation info | 1161 // via megamorphic stubs, since they don't have a map in their relocation info |
| 1163 // and so the stubs can't be harvested for the object needed for a map check. | 1162 // and so the stubs can't be harvested for the object needed for a map check. |
| 1164 if (target()->type() != Code::NORMAL) { | 1163 if (target()->type() != Code::NORMAL) { |
| 1165 TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type"); | 1164 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
| 1166 return generic_stub(); | 1165 return generic_stub(); |
| 1167 } | 1166 } |
| 1168 | 1167 |
| 1169 Handle<Map> receiver_map(receiver->map()); | 1168 Handle<Map> receiver_map(receiver->map()); |
| 1170 MapHandleList target_receiver_maps; | 1169 MapHandleList target_receiver_maps; |
| 1171 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1170 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
| 1172 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1171 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
| 1173 // yet will do so and stay there. | 1172 // yet will do so and stay there. |
| 1174 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1173 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1175 } | 1174 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1197 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1196 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1198 } | 1197 } |
| 1199 | 1198 |
| 1200 ASSERT(ic_state != GENERIC); | 1199 ASSERT(ic_state != GENERIC); |
| 1201 | 1200 |
| 1202 // Determine the list of receiver maps that this call site has seen, | 1201 // Determine the list of receiver maps that this call site has seen, |
| 1203 // adding the map that was just encountered. | 1202 // adding the map that was just encountered. |
| 1204 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1203 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
| 1205 // If the miss wasn't due to an unseen map, a polymorphic stub | 1204 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1206 // won't help, use the generic stub. | 1205 // won't help, use the generic stub. |
| 1207 TRACE_GENERIC_IC("KeyedIC", "same map added twice"); | 1206 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); |
| 1208 return generic_stub(); | 1207 return generic_stub(); |
| 1209 } | 1208 } |
| 1210 | 1209 |
| 1211 // If the maximum number of receiver maps has been exceeded, use the generic | 1210 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1212 // version of the IC. | 1211 // version of the IC. |
| 1213 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1212 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1214 TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded"); | 1213 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); |
| 1215 return generic_stub(); | 1214 return generic_stub(); |
| 1216 } | 1215 } |
| 1217 | 1216 |
| 1218 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( | 1217 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( |
| 1219 &target_receiver_maps); | 1218 &target_receiver_maps); |
| 1220 } | 1219 } |
| 1221 | 1220 |
| 1222 | 1221 |
| 1223 MaybeObject* KeyedLoadIC::Load(State state, | 1222 MaybeObject* KeyedLoadIC::Load(State state, |
| 1224 Handle<Object> object, | 1223 Handle<Object> object, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1247 if (receiver->elements()->map() == | 1246 if (receiver->elements()->map() == |
| 1248 isolate()->heap()->non_strict_arguments_elements_map()) { | 1247 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1249 stub = non_strict_arguments_stub(); | 1248 stub = non_strict_arguments_stub(); |
| 1250 } else if (receiver->HasIndexedInterceptor()) { | 1249 } else if (receiver->HasIndexedInterceptor()) { |
| 1251 stub = indexed_interceptor_stub(); | 1250 stub = indexed_interceptor_stub(); |
| 1252 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1251 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
| 1253 stub = LoadElementStub(receiver); | 1252 stub = LoadElementStub(receiver); |
| 1254 } | 1253 } |
| 1255 } | 1254 } |
| 1256 } else { | 1255 } else { |
| 1257 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); | 1256 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); |
| 1258 } | 1257 } |
| 1259 ASSERT(!stub.is_null()); | 1258 ASSERT(!stub.is_null()); |
| 1260 set_target(*stub); | 1259 set_target(*stub); |
| 1261 TRACE_IC("KeyedLoadIC", key, state, target()); | 1260 TRACE_IC("KeyedLoadIC", key, state, target()); |
| 1262 } | 1261 } |
| 1263 | 1262 |
| 1264 | 1263 |
| 1265 return Runtime::GetObjectProperty(isolate(), object, key); | 1264 return Runtime::GetObjectProperty(isolate(), object, key); |
| 1266 } | 1265 } |
| 1267 | 1266 |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 StrictModeFlag strict_mode) { | 1534 StrictModeFlag strict_mode) { |
| 1536 State ic_state = target()->ic_state(); | 1535 State ic_state = target()->ic_state(); |
| 1537 KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind) | 1536 KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind) |
| 1538 ? ALLOW_JSARRAY_GROWTH | 1537 ? ALLOW_JSARRAY_GROWTH |
| 1539 : DO_NOT_ALLOW_JSARRAY_GROWTH; | 1538 : DO_NOT_ALLOW_JSARRAY_GROWTH; |
| 1540 | 1539 |
| 1541 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1540 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
| 1542 // via megamorphic stubs, since they don't have a map in their relocation info | 1541 // via megamorphic stubs, since they don't have a map in their relocation info |
| 1543 // and so the stubs can't be harvested for the object needed for a map check. | 1542 // and so the stubs can't be harvested for the object needed for a map check. |
| 1544 if (target()->type() != Code::NORMAL) { | 1543 if (target()->type() != Code::NORMAL) { |
| 1545 TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type"); | 1544 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
| 1546 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); | 1545 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); |
| 1547 } | 1546 } |
| 1548 | 1547 |
| 1549 Handle<Map> receiver_map(receiver->map()); | 1548 Handle<Map> receiver_map(receiver->map()); |
| 1550 MapHandleList target_receiver_maps; | 1549 MapHandleList target_receiver_maps; |
| 1551 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1550 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
| 1552 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1551 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
| 1553 // yet will do so and stay there. | 1552 // yet will do so and stay there. |
| 1554 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, stub_kind); | 1553 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, stub_kind); |
| 1555 stub_kind = GetNoTransitionStubKind(stub_kind); | 1554 stub_kind = GetNoTransitionStubKind(stub_kind); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1589 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
| 1591 | 1590 |
| 1592 if (IsTransitionStubKind(stub_kind)) { | 1591 if (IsTransitionStubKind(stub_kind)) { |
| 1593 Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind); | 1592 Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind); |
| 1594 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map); | 1593 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map); |
| 1595 } | 1594 } |
| 1596 | 1595 |
| 1597 if (!map_added) { | 1596 if (!map_added) { |
| 1598 // If the miss wasn't due to an unseen map, a polymorphic stub | 1597 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1599 // won't help, use the generic stub. | 1598 // won't help, use the generic stub. |
| 1600 TRACE_GENERIC_IC("KeyedIC", "same map added twice"); | 1599 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); |
| 1601 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); | 1600 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); |
| 1602 } | 1601 } |
| 1603 | 1602 |
| 1604 // If the maximum number of receiver maps has been exceeded, use the generic | 1603 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1605 // version of the IC. | 1604 // version of the IC. |
| 1606 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1605 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1607 TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded"); | 1606 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); |
| 1608 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); | 1607 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); |
| 1609 } | 1608 } |
| 1610 | 1609 |
| 1611 if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) == | 1610 if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) == |
| 1612 ALLOW_JSARRAY_GROWTH)) { | 1611 ALLOW_JSARRAY_GROWTH)) { |
| 1613 grow_mode = ALLOW_JSARRAY_GROWTH; | 1612 grow_mode = ALLOW_JSARRAY_GROWTH; |
| 1614 } | 1613 } |
| 1615 | 1614 |
| 1616 return isolate()->stub_cache()->ComputeStoreElementPolymorphic( | 1615 return isolate()->stub_cache()->ComputeStoreElementPolymorphic( |
| 1617 &target_receiver_maps, grow_mode, strict_mode); | 1616 &target_receiver_maps, grow_mode, strict_mode); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1746 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1745 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1747 if (receiver->elements()->map() == | 1746 if (receiver->elements()->map() == |
| 1748 isolate()->heap()->non_strict_arguments_elements_map()) { | 1747 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1749 stub = non_strict_arguments_stub(); | 1748 stub = non_strict_arguments_stub(); |
| 1750 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1749 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
| 1751 StubKind stub_kind = GetStubKind(receiver, key, value); | 1750 StubKind stub_kind = GetStubKind(receiver, key, value); |
| 1752 stub = StoreElementStub(receiver, stub_kind, strict_mode); | 1751 stub = StoreElementStub(receiver, stub_kind, strict_mode); |
| 1753 } | 1752 } |
| 1754 } | 1753 } |
| 1755 } else { | 1754 } else { |
| 1756 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); | 1755 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); |
| 1757 } | 1756 } |
| 1758 ASSERT(!stub.is_null()); | 1757 ASSERT(!stub.is_null()); |
| 1759 set_target(*stub); | 1758 set_target(*stub); |
| 1760 TRACE_IC("KeyedStoreIC", key, state, target()); | 1759 TRACE_IC("KeyedStoreIC", key, state, target()); |
| 1761 } | 1760 } |
| 1762 | 1761 |
| 1763 return Runtime::SetObjectProperty( | 1762 return Runtime::SetObjectProperty( |
| 1764 isolate(), object , key, value, NONE, strict_mode); | 1763 isolate(), object , key, value, NONE, strict_mode); |
| 1765 } | 1764 } |
| 1766 | 1765 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1899 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1898 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 1900 return ic.Load(state, | 1899 return ic.Load(state, |
| 1901 args.at<Object>(0), | 1900 args.at<Object>(0), |
| 1902 args.at<Object>(1), | 1901 args.at<Object>(1), |
| 1903 MISS_FORCE_GENERIC); | 1902 MISS_FORCE_GENERIC); |
| 1904 } | 1903 } |
| 1905 | 1904 |
| 1906 | 1905 |
| 1907 // Used from ic-<arch>.cc. | 1906 // Used from ic-<arch>.cc. |
| 1908 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 1907 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
| 1909 HandleScope scope; | 1908 HandleScope scope(isolate); |
| 1910 ASSERT(args.length() == 3); | 1909 ASSERT(args.length() == 3); |
| 1911 StoreIC ic(isolate); | 1910 StoreIC ic(isolate); |
| 1912 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1911 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 1913 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1912 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 1914 return ic.Store(state, | 1913 return ic.Store(state, |
| 1915 Code::GetStrictMode(extra_ic_state), | 1914 Code::GetStrictMode(extra_ic_state), |
| 1916 args.at<Object>(0), | 1915 args.at<Object>(0), |
| 1917 args.at<String>(1), | 1916 args.at<String>(1), |
| 1918 args.at<Object>(2)); | 1917 args.at<Object>(2)); |
| 1919 } | 1918 } |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2142 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); | 2141 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); |
| 2143 | 2142 |
| 2144 UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand); | 2143 UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand); |
| 2145 type = UnaryOpIC::ComputeNewType(type, previous_type); | 2144 type = UnaryOpIC::ComputeNewType(type, previous_type); |
| 2146 | 2145 |
| 2147 UnaryOpStub stub(op, mode, type); | 2146 UnaryOpStub stub(op, mode, type); |
| 2148 Handle<Code> code = stub.GetCode(); | 2147 Handle<Code> code = stub.GetCode(); |
| 2149 if (!code.is_null()) { | 2148 if (!code.is_null()) { |
| 2150 if (FLAG_trace_ic) { | 2149 if (FLAG_trace_ic) { |
| 2151 PrintF("[UnaryOpIC in "); | 2150 PrintF("[UnaryOpIC in "); |
| 2152 JavaScriptFrame::PrintTop(stdout, false, true); | 2151 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
| 2153 PrintF(" (%s->%s)#%s @ %p]\n", | 2152 PrintF(" (%s->%s)#%s @ %p]\n", |
| 2154 UnaryOpIC::GetName(previous_type), | 2153 UnaryOpIC::GetName(previous_type), |
| 2155 UnaryOpIC::GetName(type), | 2154 UnaryOpIC::GetName(type), |
| 2156 Token::Name(op), | 2155 Token::Name(op), |
| 2157 static_cast<void*>(*code)); | 2156 static_cast<void*>(*code)); |
| 2158 } | 2157 } |
| 2159 UnaryOpIC ic(isolate); | 2158 UnaryOpIC ic(isolate); |
| 2160 ic.patch(*code); | 2159 ic.patch(*code); |
| 2161 } | 2160 } |
| 2162 | 2161 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2271 result_type = BinaryOpIC::HEAP_NUMBER; | 2270 result_type = BinaryOpIC::HEAP_NUMBER; |
| 2272 } | 2271 } |
| 2273 } | 2272 } |
| 2274 | 2273 |
| 2275 BinaryOpStub stub(key, new_left, new_right, result_type); | 2274 BinaryOpStub stub(key, new_left, new_right, result_type); |
| 2276 Handle<Code> code = stub.GetCode(); | 2275 Handle<Code> code = stub.GetCode(); |
| 2277 if (!code.is_null()) { | 2276 if (!code.is_null()) { |
| 2278 #ifdef DEBUG | 2277 #ifdef DEBUG |
| 2279 if (FLAG_trace_ic) { | 2278 if (FLAG_trace_ic) { |
| 2280 PrintF("[BinaryOpIC in "); | 2279 PrintF("[BinaryOpIC in "); |
| 2281 JavaScriptFrame::PrintTop(stdout, false, true); | 2280 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
| 2282 PrintF(" ((%s+%s)->((%s+%s)->%s))#%s @ %p]\n", | 2281 PrintF(" ((%s+%s)->((%s+%s)->%s))#%s @ %p]\n", |
| 2283 BinaryOpIC::GetName(previous_left), | 2282 BinaryOpIC::GetName(previous_left), |
| 2284 BinaryOpIC::GetName(previous_right), | 2283 BinaryOpIC::GetName(previous_right), |
| 2285 BinaryOpIC::GetName(new_left), | 2284 BinaryOpIC::GetName(new_left), |
| 2286 BinaryOpIC::GetName(new_right), | 2285 BinaryOpIC::GetName(new_right), |
| 2287 BinaryOpIC::GetName(result_type), | 2286 BinaryOpIC::GetName(result_type), |
| 2288 Token::Name(op), | 2287 Token::Name(op), |
| 2289 static_cast<void*>(*code)); | 2288 static_cast<void*>(*code)); |
| 2290 } | 2289 } |
| 2291 #endif | 2290 #endif |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2473 case KNOWN_OBJECTS: | 2472 case KNOWN_OBJECTS: |
| 2474 case GENERIC: | 2473 case GENERIC: |
| 2475 return GENERIC; | 2474 return GENERIC; |
| 2476 } | 2475 } |
| 2477 UNREACHABLE(); | 2476 UNREACHABLE(); |
| 2478 return GENERIC; // Make the compiler happy. | 2477 return GENERIC; // Make the compiler happy. |
| 2479 } | 2478 } |
| 2480 | 2479 |
| 2481 | 2480 |
| 2482 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { | 2481 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
| 2483 HandleScope scope; | 2482 HandleScope scope(isolate()); |
| 2484 State previous_left, previous_right, previous_state; | 2483 State previous_left, previous_right, previous_state; |
| 2485 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2484 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
| 2486 &previous_right, &previous_state, NULL); | 2485 &previous_right, &previous_state, NULL); |
| 2487 State new_left = InputState(previous_left, x); | 2486 State new_left = InputState(previous_left, x); |
| 2488 State new_right = InputState(previous_right, y); | 2487 State new_right = InputState(previous_right, y); |
| 2489 State state = TargetState(previous_state, previous_left, previous_right, | 2488 State state = TargetState(previous_state, previous_left, previous_right, |
| 2490 HasInlinedSmiCode(address()), x, y); | 2489 HasInlinedSmiCode(address()), x, y); |
| 2491 ICCompareStub stub(op_, new_left, new_right, state); | 2490 ICCompareStub stub(op_, new_left, new_right, state); |
| 2492 if (state == KNOWN_OBJECTS) { | 2491 if (state == KNOWN_OBJECTS) { |
| 2493 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); | 2492 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); |
| 2494 } | 2493 } |
| 2495 set_target(*stub.GetCode()); | 2494 set_target(*stub.GetCode()); |
| 2496 | 2495 |
| 2497 #ifdef DEBUG | 2496 #ifdef DEBUG |
| 2498 if (FLAG_trace_ic) { | 2497 if (FLAG_trace_ic) { |
| 2499 PrintF("[CompareIC in "); | 2498 PrintF("[CompareIC in "); |
| 2500 JavaScriptFrame::PrintTop(stdout, false, true); | 2499 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2501 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 2500 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
| 2502 GetStateName(previous_left), | 2501 GetStateName(previous_left), |
| 2503 GetStateName(previous_right), | 2502 GetStateName(previous_right), |
| 2504 GetStateName(previous_state), | 2503 GetStateName(previous_state), |
| 2505 GetStateName(new_left), | 2504 GetStateName(new_left), |
| 2506 GetStateName(new_right), | 2505 GetStateName(new_right), |
| 2507 GetStateName(state), | 2506 GetStateName(state), |
| 2508 Token::Name(op_), | 2507 Token::Name(op_), |
| 2509 static_cast<void*>(*stub.GetCode())); | 2508 static_cast<void*>(*stub.GetCode())); |
| 2510 } | 2509 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2559 #undef ADDR | 2558 #undef ADDR |
| 2560 }; | 2559 }; |
| 2561 | 2560 |
| 2562 | 2561 |
| 2563 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2562 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2564 return IC_utilities[id]; | 2563 return IC_utilities[id]; |
| 2565 } | 2564 } |
| 2566 | 2565 |
| 2567 | 2566 |
| 2568 } } // namespace v8::internal | 2567 } } // namespace v8::internal |
| OLD | NEW |