| 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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 HandleScope scope(isolate()); | 153 HandleScope scope(isolate()); |
| 154 // Compute the JavaScript frame for the frame pointer of this IC | 154 // Compute the JavaScript frame for the frame pointer of this IC |
| 155 // structure. We need this to be able to find the function | 155 // structure. We need this to be able to find the function |
| 156 // corresponding to the frame. | 156 // corresponding to the frame. |
| 157 StackFrameIterator it(isolate()); | 157 StackFrameIterator it(isolate()); |
| 158 while (it.frame()->fp() != this->fp()) it.Advance(); | 158 while (it.frame()->fp() != this->fp()) it.Advance(); |
| 159 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); | 159 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); |
| 160 // Find the function on the stack and both the active code for the | 160 // Find the function on the stack and both the active code for the |
| 161 // function and the original code. | 161 // function and the original code. |
| 162 JSFunction* function = JSFunction::cast(frame->function()); | 162 JSFunction* function = JSFunction::cast(frame->function()); |
| 163 Handle<SharedFunctionInfo> shared(function->shared()); | 163 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
| 164 Code* code = shared->code(); | 164 Code* code = shared->code(); |
| 165 ASSERT(Debug::HasDebugInfo(shared)); | 165 ASSERT(Debug::HasDebugInfo(shared)); |
| 166 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); | 166 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); |
| 167 ASSERT(original_code->IsCode()); | 167 ASSERT(original_code->IsCode()); |
| 168 // Get the address of the call site in the active code. This is the | 168 // Get the address of the call site in the active code. This is the |
| 169 // place where the call to DebugBreakXXX is and where the IC | 169 // place where the call to DebugBreakXXX is and where the IC |
| 170 // normally would be. | 170 // normally would be. |
| 171 Address addr = Assembler::target_address_from_return_address(pc()); | 171 Address addr = Assembler::target_address_from_return_address(pc()); |
| 172 // Return the address in the original code. This is the place where | 172 // Return the address in the original code. This is the place where |
| 173 // the call which has been overwritten by the DebugBreakXXX resides | 173 // the call which has been overwritten by the DebugBreakXXX resides |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 // without actual getter. | 428 // without actual getter. |
| 429 while (true) { | 429 while (true) { |
| 430 object->Lookup(*name, lookup); | 430 object->Lookup(*name, lookup); |
| 431 // Besides normal conditions (property not found or it's not | 431 // Besides normal conditions (property not found or it's not |
| 432 // an interceptor), bail out if lookup is not cacheable: we won't | 432 // an interceptor), bail out if lookup is not cacheable: we won't |
| 433 // be able to IC it anyway and regular lookup should work fine. | 433 // be able to IC it anyway and regular lookup should work fine. |
| 434 if (!lookup->IsInterceptor() || !lookup->IsCacheable()) { | 434 if (!lookup->IsInterceptor() || !lookup->IsCacheable()) { |
| 435 return; | 435 return; |
| 436 } | 436 } |
| 437 | 437 |
| 438 Handle<JSObject> holder(lookup->holder()); | 438 Handle<JSObject> holder(lookup->holder(), lookup->isolate()); |
| 439 if (HasInterceptorGetter(*holder)) { | 439 if (HasInterceptorGetter(*holder)) { |
| 440 return; | 440 return; |
| 441 } | 441 } |
| 442 | 442 |
| 443 holder->LocalLookupRealNamedProperty(*name, lookup); | 443 holder->LocalLookupRealNamedProperty(*name, lookup); |
| 444 if (lookup->IsFound()) { | 444 if (lookup->IsFound()) { |
| 445 ASSERT(!lookup->IsInterceptor()); | 445 ASSERT(!lookup->IsInterceptor()); |
| 446 return; | 446 return; |
| 447 } | 447 } |
| 448 | 448 |
| 449 Handle<Object> proto(holder->GetPrototype(), name->GetIsolate()); | 449 Handle<Object> proto(holder->GetPrototype(), lookup->isolate()); |
| 450 if (proto->IsNull()) { | 450 if (proto->IsNull()) { |
| 451 ASSERT(!lookup->IsFound()); | 451 ASSERT(!lookup->IsFound()); |
| 452 return; | 452 return; |
| 453 } | 453 } |
| 454 | 454 |
| 455 object = proto; | 455 object = proto; |
| 456 } | 456 } |
| 457 } | 457 } |
| 458 | 458 |
| 459 | 459 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 return false; | 629 return false; |
| 630 } | 630 } |
| 631 | 631 |
| 632 | 632 |
| 633 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, | 633 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, |
| 634 State state, | 634 State state, |
| 635 Code::ExtraICState extra_state, | 635 Code::ExtraICState extra_state, |
| 636 Handle<Object> object, | 636 Handle<Object> object, |
| 637 Handle<String> name) { | 637 Handle<String> name) { |
| 638 int argc = target()->arguments_count(); | 638 int argc = target()->arguments_count(); |
| 639 Handle<JSObject> holder(lookup->holder()); | 639 Handle<JSObject> holder(lookup->holder(), isolate()); |
| 640 switch (lookup->type()) { | 640 switch (lookup->type()) { |
| 641 case FIELD: { | 641 case FIELD: { |
| 642 PropertyIndex index = lookup->GetFieldIndex(); | 642 PropertyIndex index = lookup->GetFieldIndex(); |
| 643 return isolate()->stub_cache()->ComputeCallField( | 643 return isolate()->stub_cache()->ComputeCallField( |
| 644 argc, kind_, extra_state, name, object, holder, index); | 644 argc, kind_, extra_state, name, object, holder, index); |
| 645 } | 645 } |
| 646 case CONSTANT_FUNCTION: { | 646 case CONSTANT_FUNCTION: { |
| 647 // Get the constant function and compute the code stub for this | 647 // Get the constant function and compute the code stub for this |
| 648 // call; used for rewriting to monomorphic state and making sure | 648 // call; used for rewriting to monomorphic state and making sure |
| 649 // that the code stub is in the stub cache. | 649 // that the code stub is in the stub cache. |
| 650 Handle<JSFunction> function(lookup->GetConstantFunction()); | 650 Handle<JSFunction> function(lookup->GetConstantFunction(), isolate()); |
| 651 return isolate()->stub_cache()->ComputeCallConstant( | 651 return isolate()->stub_cache()->ComputeCallConstant( |
| 652 argc, kind_, extra_state, name, object, holder, function); | 652 argc, kind_, extra_state, name, object, holder, function); |
| 653 } | 653 } |
| 654 case NORMAL: { | 654 case NORMAL: { |
| 655 // If we return a null handle, the IC will not be patched. | 655 // If we return a null handle, the IC will not be patched. |
| 656 if (!object->IsJSObject()) return Handle<Code>::null(); | 656 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 657 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 657 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 658 | 658 |
| 659 if (holder->IsGlobalObject()) { | 659 if (holder->IsGlobalObject()) { |
| 660 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 660 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 661 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); | 661 Handle<JSGlobalPropertyCell> cell( |
| 662 global->GetPropertyCell(lookup), isolate()); |
| 662 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); | 663 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); |
| 663 Handle<JSFunction> function(JSFunction::cast(cell->value())); | 664 Handle<JSFunction> function(JSFunction::cast(cell->value())); |
| 664 return isolate()->stub_cache()->ComputeCallGlobal( | 665 return isolate()->stub_cache()->ComputeCallGlobal( |
| 665 argc, kind_, extra_state, name, receiver, global, cell, function); | 666 argc, kind_, extra_state, name, receiver, global, cell, function); |
| 666 } else { | 667 } else { |
| 667 // There is only one shared stub for calling normalized | 668 // There is only one shared stub for calling normalized |
| 668 // properties. It does not traverse the prototype chain, so the | 669 // properties. It does not traverse the prototype chain, so the |
| 669 // property must be found in the receiver for the stub to be | 670 // property must be found in the receiver for the stub to be |
| 670 // applicable. | 671 // applicable. |
| 671 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); | 672 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 UpdateMegamorphicCache(map, *name, target()); | 740 UpdateMegamorphicCache(map, *name, target()); |
| 740 } | 741 } |
| 741 } | 742 } |
| 742 set_target(*code); | 743 set_target(*code); |
| 743 break; | 744 break; |
| 744 case MEGAMORPHIC: { | 745 case MEGAMORPHIC: { |
| 745 // Cache code holding map should be consistent with | 746 // Cache code holding map should be consistent with |
| 746 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 747 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. |
| 747 Handle<JSObject> cache_object = object->IsJSObject() | 748 Handle<JSObject> cache_object = object->IsJSObject() |
| 748 ? Handle<JSObject>::cast(object) | 749 ? Handle<JSObject>::cast(object) |
| 749 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))); | 750 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), |
| 751 isolate()); |
| 750 // Update the stub cache. | 752 // Update the stub cache. |
| 751 UpdateMegamorphicCache(cache_object->map(), *name, *code); | 753 UpdateMegamorphicCache(cache_object->map(), *name, *code); |
| 752 break; | 754 break; |
| 753 } | 755 } |
| 754 case DEBUG_STUB: | 756 case DEBUG_STUB: |
| 755 break; | 757 break; |
| 756 case POLYMORPHIC: | 758 case POLYMORPHIC: |
| 757 case GENERIC: | 759 case GENERIC: |
| 758 UNREACHABLE(); | 760 UNREACHABLE(); |
| 759 break; | 761 break; |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 return isolate()->stub_cache()->ComputeLoadField( | 1191 return isolate()->stub_cache()->ComputeLoadField( |
| 1190 name, receiver, holder, lookup->GetFieldIndex()); | 1192 name, receiver, holder, lookup->GetFieldIndex()); |
| 1191 case CONSTANT_FUNCTION: { | 1193 case CONSTANT_FUNCTION: { |
| 1192 Handle<JSFunction> constant(lookup->GetConstantFunction()); | 1194 Handle<JSFunction> constant(lookup->GetConstantFunction()); |
| 1193 return isolate()->stub_cache()->ComputeLoadConstant( | 1195 return isolate()->stub_cache()->ComputeLoadConstant( |
| 1194 name, receiver, holder, constant); | 1196 name, receiver, holder, constant); |
| 1195 } | 1197 } |
| 1196 case NORMAL: | 1198 case NORMAL: |
| 1197 if (holder->IsGlobalObject()) { | 1199 if (holder->IsGlobalObject()) { |
| 1198 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 1200 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 1199 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); | 1201 Handle<JSGlobalPropertyCell> cell( |
| 1202 global->GetPropertyCell(lookup), isolate()); |
| 1200 return isolate()->stub_cache()->ComputeLoadGlobal( | 1203 return isolate()->stub_cache()->ComputeLoadGlobal( |
| 1201 name, receiver, global, cell, lookup->IsDontDelete()); | 1204 name, receiver, global, cell, lookup->IsDontDelete()); |
| 1202 } | 1205 } |
| 1203 // There is only one shared stub for loading normalized | 1206 // There is only one shared stub for loading normalized |
| 1204 // properties. It does not traverse the prototype chain, so the | 1207 // properties. It does not traverse the prototype chain, so the |
| 1205 // property must be found in the receiver for the stub to be | 1208 // property must be found in the receiver for the stub to be |
| 1206 // applicable. | 1209 // applicable. |
| 1207 if (!holder.is_identical_to(receiver)) break; | 1210 if (!holder.is_identical_to(receiver)) break; |
| 1208 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver); | 1211 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver); |
| 1209 case CALLBACKS: { | 1212 case CALLBACKS: { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 State ic_state = target()->ic_state(); | 1268 State ic_state = target()->ic_state(); |
| 1266 | 1269 |
| 1267 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1270 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
| 1268 // via megamorphic stubs, since they don't have a map in their relocation info | 1271 // via megamorphic stubs, since they don't have a map in their relocation info |
| 1269 // and so the stubs can't be harvested for the object needed for a map check. | 1272 // and so the stubs can't be harvested for the object needed for a map check. |
| 1270 if (target()->type() != Code::NORMAL) { | 1273 if (target()->type() != Code::NORMAL) { |
| 1271 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); | 1274 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
| 1272 return generic_stub(); | 1275 return generic_stub(); |
| 1273 } | 1276 } |
| 1274 | 1277 |
| 1275 Handle<Map> receiver_map(receiver->map()); | 1278 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1276 MapHandleList target_receiver_maps; | 1279 MapHandleList target_receiver_maps; |
| 1277 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1280 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
| 1278 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1281 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
| 1279 // yet will do so and stay there. | 1282 // yet will do so and stay there. |
| 1280 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1283 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1281 } | 1284 } |
| 1282 | 1285 |
| 1283 if (target() == *string_stub()) { | 1286 if (target() == *string_stub()) { |
| 1284 target_receiver_maps.Add(isolate()->factory()->string_map()); | 1287 target_receiver_maps.Add(isolate()->factory()->string_map()); |
| 1285 } else { | 1288 } else { |
| 1286 GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps); | 1289 GetReceiverMapsForStub(Handle<Code>(target(), isolate()), |
| 1290 &target_receiver_maps); |
| 1287 if (target_receiver_maps.length() == 0) { | 1291 if (target_receiver_maps.length() == 0) { |
| 1288 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1292 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1289 } | 1293 } |
| 1290 } | 1294 } |
| 1291 | 1295 |
| 1292 // The first time a receiver is seen that is a transitioned version of the | 1296 // The first time a receiver is seen that is a transitioned version of the |
| 1293 // previous monomorphic receiver type, assume the new ElementsKind is the | 1297 // previous monomorphic receiver type, assume the new ElementsKind is the |
| 1294 // monomorphic type. This benefits global arrays that only transition | 1298 // monomorphic type. This benefits global arrays that only transition |
| 1295 // once, and all call sites accessing them are faster if they remain | 1299 // once, and all call sites accessing them are faster if they remain |
| 1296 // monomorphic. If this optimistic assumption is not true, the IC will | 1300 // monomorphic. If this optimistic assumption is not true, the IC will |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1372 } | 1376 } |
| 1373 | 1377 |
| 1374 | 1378 |
| 1375 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, | 1379 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, |
| 1376 Handle<JSObject> receiver, | 1380 Handle<JSObject> receiver, |
| 1377 Handle<String> name) { | 1381 Handle<String> name) { |
| 1378 // Bail out if we didn't find a result. | 1382 // Bail out if we didn't find a result. |
| 1379 if (!lookup->IsProperty()) return Handle<Code>::null(); | 1383 if (!lookup->IsProperty()) return Handle<Code>::null(); |
| 1380 | 1384 |
| 1381 // Compute a monomorphic stub. | 1385 // Compute a monomorphic stub. |
| 1382 Handle<JSObject> holder(lookup->holder()); | 1386 Handle<JSObject> holder(lookup->holder(), isolate()); |
| 1383 switch (lookup->type()) { | 1387 switch (lookup->type()) { |
| 1384 case FIELD: | 1388 case FIELD: |
| 1385 return isolate()->stub_cache()->ComputeKeyedLoadField( | 1389 return isolate()->stub_cache()->ComputeKeyedLoadField( |
| 1386 name, receiver, holder, lookup->GetFieldIndex()); | 1390 name, receiver, holder, lookup->GetFieldIndex()); |
| 1387 case CONSTANT_FUNCTION: { | 1391 case CONSTANT_FUNCTION: { |
| 1388 Handle<JSFunction> constant(lookup->GetConstantFunction()); | 1392 Handle<JSFunction> constant(lookup->GetConstantFunction(), isolate()); |
| 1389 return isolate()->stub_cache()->ComputeKeyedLoadConstant( | 1393 return isolate()->stub_cache()->ComputeKeyedLoadConstant( |
| 1390 name, receiver, holder, constant); | 1394 name, receiver, holder, constant); |
| 1391 } | 1395 } |
| 1392 case CALLBACKS: { | 1396 case CALLBACKS: { |
| 1393 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate()); | 1397 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate()); |
| 1394 // TODO(dcarney): Handle DeclaredAccessorInfo correctly. | 1398 // TODO(dcarney): Handle DeclaredAccessorInfo correctly. |
| 1395 if (!callback_object->IsExecutableAccessorInfo()) break; | 1399 if (!callback_object->IsExecutableAccessorInfo()) break; |
| 1396 Handle<ExecutableAccessorInfo> callback = | 1400 Handle<ExecutableAccessorInfo> callback = |
| 1397 Handle<ExecutableAccessorInfo>::cast(callback_object); | 1401 Handle<ExecutableAccessorInfo>::cast(callback_object); |
| 1398 if (v8::ToCData<Address>(callback->getter()) == 0) break; | 1402 if (v8::ToCData<Address>(callback->getter()) == 0) break; |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 case FIELD: | 1575 case FIELD: |
| 1572 return isolate()->stub_cache()->ComputeStoreField( | 1576 return isolate()->stub_cache()->ComputeStoreField( |
| 1573 name, receiver, lookup->GetFieldIndex().field_index(), | 1577 name, receiver, lookup->GetFieldIndex().field_index(), |
| 1574 Handle<Map>::null(), strict_mode); | 1578 Handle<Map>::null(), strict_mode); |
| 1575 case NORMAL: | 1579 case NORMAL: |
| 1576 if (receiver->IsGlobalObject()) { | 1580 if (receiver->IsGlobalObject()) { |
| 1577 // The stub generated for the global object picks the value directly | 1581 // The stub generated for the global object picks the value directly |
| 1578 // from the property cell. So the property must be directly on the | 1582 // from the property cell. So the property must be directly on the |
| 1579 // global object. | 1583 // global object. |
| 1580 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1584 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
| 1581 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); | 1585 Handle<JSGlobalPropertyCell> cell( |
| 1586 global->GetPropertyCell(lookup), isolate()); |
| 1582 return isolate()->stub_cache()->ComputeStoreGlobal( | 1587 return isolate()->stub_cache()->ComputeStoreGlobal( |
| 1583 name, global, cell, strict_mode); | 1588 name, global, cell, strict_mode); |
| 1584 } | 1589 } |
| 1585 if (!holder.is_identical_to(receiver)) break; | 1590 if (!holder.is_identical_to(receiver)) break; |
| 1586 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); | 1591 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); |
| 1587 case CALLBACKS: { | 1592 case CALLBACKS: { |
| 1588 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1593 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
| 1589 if (callback->IsExecutableAccessorInfo()) { | 1594 if (callback->IsExecutableAccessorInfo()) { |
| 1590 Handle<ExecutableAccessorInfo> info = | 1595 Handle<ExecutableAccessorInfo> info = |
| 1591 Handle<ExecutableAccessorInfo>::cast(callback); | 1596 Handle<ExecutableAccessorInfo>::cast(callback); |
| 1592 if (v8::ToCData<Address>(info->setter()) == 0) break; | 1597 if (v8::ToCData<Address>(info->setter()) == 0) break; |
| 1593 if (!holder->HasFastProperties()) break; | 1598 if (!holder->HasFastProperties()) break; |
| 1594 if (!info->IsCompatibleReceiver(*receiver)) break; | 1599 if (!info->IsCompatibleReceiver(*receiver)) break; |
| 1595 return isolate()->stub_cache()->ComputeStoreCallback( | 1600 return isolate()->stub_cache()->ComputeStoreCallback( |
| 1596 name, receiver, holder, info, strict_mode); | 1601 name, receiver, holder, info, strict_mode); |
| 1597 } else if (callback->IsAccessorPair()) { | 1602 } else if (callback->IsAccessorPair()) { |
| 1598 Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter(), | 1603 Handle<Object> setter( |
| 1599 isolate()); | 1604 Handle<AccessorPair>::cast(callback)->setter(), isolate()); |
| 1600 if (!setter->IsJSFunction()) break; | 1605 if (!setter->IsJSFunction()) break; |
| 1601 if (holder->IsGlobalObject()) break; | 1606 if (holder->IsGlobalObject()) break; |
| 1602 if (!holder->HasFastProperties()) break; | 1607 if (!holder->HasFastProperties()) break; |
| 1603 return isolate()->stub_cache()->ComputeStoreViaSetter( | 1608 return isolate()->stub_cache()->ComputeStoreViaSetter( |
| 1604 name, receiver, holder, Handle<JSFunction>::cast(setter), | 1609 name, receiver, holder, Handle<JSFunction>::cast(setter), |
| 1605 strict_mode); | 1610 strict_mode); |
| 1606 } | 1611 } |
| 1607 // TODO(dcarney): Handle correctly. | 1612 // TODO(dcarney): Handle correctly. |
| 1608 if (callback->IsDeclaredAccessorInfo()) break; | 1613 if (callback->IsDeclaredAccessorInfo()) break; |
| 1609 ASSERT(callback->IsForeign()); | 1614 ASSERT(callback->IsForeign()); |
| 1610 // No IC support for old-style native accessors. | 1615 // No IC support for old-style native accessors. |
| 1611 break; | 1616 break; |
| 1612 } | 1617 } |
| 1613 case INTERCEPTOR: | 1618 case INTERCEPTOR: |
| 1614 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1619 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); |
| 1615 return isolate()->stub_cache()->ComputeStoreInterceptor( | 1620 return isolate()->stub_cache()->ComputeStoreInterceptor( |
| 1616 name, receiver, strict_mode); | 1621 name, receiver, strict_mode); |
| 1617 case CONSTANT_FUNCTION: | 1622 case CONSTANT_FUNCTION: |
| 1618 break; | 1623 break; |
| 1619 case TRANSITION: { | 1624 case TRANSITION: { |
| 1620 Handle<Map> transition(lookup->GetTransitionTarget()); | 1625 Handle<Map> transition(lookup->GetTransitionTarget(), isolate()); |
| 1621 int descriptor = transition->LastAdded(); | 1626 int descriptor = transition->LastAdded(); |
| 1622 | 1627 |
| 1623 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1628 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
| 1624 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1629 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
| 1625 | 1630 |
| 1626 if (details.type() != FIELD || details.attributes() != NONE) break; | 1631 if (details.type() != FIELD || details.attributes() != NONE) break; |
| 1627 | 1632 |
| 1628 int field_index = target_descriptors->GetFieldIndex(descriptor); | 1633 int field_index = target_descriptors->GetFieldIndex(descriptor); |
| 1629 return isolate()->stub_cache()->ComputeStoreField( | 1634 return isolate()->stub_cache()->ComputeStoreField( |
| 1630 name, receiver, field_index, transition, strict_mode); | 1635 name, receiver, field_index, transition, strict_mode); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1654 // TODO(danno): We'll soon handle MONOMORPHIC ICs that also support | 1659 // TODO(danno): We'll soon handle MONOMORPHIC ICs that also support |
| 1655 // copying COW arrays and silently ignoring some OOB stores into external | 1660 // copying COW arrays and silently ignoring some OOB stores into external |
| 1656 // arrays, but for now use the generic. | 1661 // arrays, but for now use the generic. |
| 1657 TRACE_GENERIC_IC(isolate(), "KeyedIC", "COW/OOB external array"); | 1662 TRACE_GENERIC_IC(isolate(), "KeyedIC", "COW/OOB external array"); |
| 1658 return strict_mode == kStrictMode | 1663 return strict_mode == kStrictMode |
| 1659 ? generic_stub_strict() | 1664 ? generic_stub_strict() |
| 1660 : generic_stub(); | 1665 : generic_stub(); |
| 1661 } | 1666 } |
| 1662 | 1667 |
| 1663 State ic_state = target()->ic_state(); | 1668 State ic_state = target()->ic_state(); |
| 1664 Handle<Map> receiver_map(receiver->map()); | 1669 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1665 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1670 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
| 1666 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1671 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
| 1667 // yet will do so and stay there. | 1672 // yet will do so and stay there. |
| 1668 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); | 1673 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); |
| 1669 store_mode = GetNonTransitioningStoreMode(store_mode); | 1674 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1670 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1675 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1671 monomorphic_map, strict_mode, store_mode); | 1676 monomorphic_map, strict_mode, store_mode); |
| 1672 } | 1677 } |
| 1673 | 1678 |
| 1674 MapHandleList target_receiver_maps; | 1679 MapHandleList target_receiver_maps; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1787 case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE: | 1792 case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE: |
| 1788 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE: | 1793 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE: |
| 1789 return JSObject::GetElementsTransitionMap(receiver, | 1794 return JSObject::GetElementsTransitionMap(receiver, |
| 1790 FAST_HOLEY_DOUBLE_ELEMENTS); | 1795 FAST_HOLEY_DOUBLE_ELEMENTS); |
| 1791 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: | 1796 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: |
| 1792 ASSERT(receiver->map()->has_external_array_elements()); | 1797 ASSERT(receiver->map()->has_external_array_elements()); |
| 1793 // Fall through | 1798 // Fall through |
| 1794 case STORE_NO_TRANSITION_HANDLE_COW: | 1799 case STORE_NO_TRANSITION_HANDLE_COW: |
| 1795 case STANDARD_STORE: | 1800 case STANDARD_STORE: |
| 1796 case STORE_AND_GROW_NO_TRANSITION: | 1801 case STORE_AND_GROW_NO_TRANSITION: |
| 1797 return Handle<Map>(receiver->map()); | 1802 return Handle<Map>(receiver->map(), isolate()); |
| 1798 } | 1803 } |
| 1799 return Handle<Map>::null(); | 1804 return Handle<Map>::null(); |
| 1800 } | 1805 } |
| 1801 | 1806 |
| 1802 | 1807 |
| 1803 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, | 1808 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, |
| 1804 int index) { | 1809 int index) { |
| 1805 if (receiver->IsJSArray()) { | 1810 if (receiver->IsJSArray()) { |
| 1806 return JSArray::cast(*receiver)->length()->IsSmi() && | 1811 return JSArray::cast(*receiver)->length()->IsSmi() && |
| 1807 index >= Smi::cast(JSArray::cast(*receiver)->length())->value(); | 1812 index >= Smi::cast(JSArray::cast(*receiver)->length())->value(); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1937 Handle<String> name) { | 1942 Handle<String> name) { |
| 1938 // If the property has a non-field type allowing map transitions | 1943 // If the property has a non-field type allowing map transitions |
| 1939 // where there is extra room in the object, we leave the IC in its | 1944 // where there is extra room in the object, we leave the IC in its |
| 1940 // current state. | 1945 // current state. |
| 1941 switch (lookup->type()) { | 1946 switch (lookup->type()) { |
| 1942 case FIELD: | 1947 case FIELD: |
| 1943 return isolate()->stub_cache()->ComputeKeyedStoreField( | 1948 return isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1944 name, receiver, lookup->GetFieldIndex().field_index(), | 1949 name, receiver, lookup->GetFieldIndex().field_index(), |
| 1945 Handle<Map>::null(), strict_mode); | 1950 Handle<Map>::null(), strict_mode); |
| 1946 case TRANSITION: { | 1951 case TRANSITION: { |
| 1947 Handle<Map> transition(lookup->GetTransitionTarget()); | 1952 Handle<Map> transition(lookup->GetTransitionTarget(), isolate()); |
| 1948 int descriptor = transition->LastAdded(); | 1953 int descriptor = transition->LastAdded(); |
| 1949 | 1954 |
| 1950 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1955 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
| 1951 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1956 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
| 1952 | 1957 |
| 1953 if (details.type() == FIELD && details.attributes() == NONE) { | 1958 if (details.type() == FIELD && details.attributes() == NONE) { |
| 1954 int field_index = target_descriptors->GetFieldIndex(descriptor); | 1959 int field_index = target_descriptors->GetFieldIndex(descriptor); |
| 1955 return isolate()->stub_cache()->ComputeKeyedStoreField( | 1960 return isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1956 name, receiver, field_index, transition, strict_mode); | 1961 name, receiver, field_index, transition, strict_mode); |
| 1957 } | 1962 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2016 KeyedCallIC ic(isolate); | 2021 KeyedCallIC ic(isolate); |
| 2017 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2022 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 2018 MaybeObject* maybe_result = | 2023 MaybeObject* maybe_result = |
| 2019 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 2024 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); |
| 2020 // Result could be a function or a failure. | 2025 // Result could be a function or a failure. |
| 2021 JSFunction* raw_function = NULL; | 2026 JSFunction* raw_function = NULL; |
| 2022 if (!maybe_result->To(&raw_function)) return maybe_result; | 2027 if (!maybe_result->To(&raw_function)) return maybe_result; |
| 2023 | 2028 |
| 2024 if (raw_function->is_compiled()) return raw_function; | 2029 if (raw_function->is_compiled()) return raw_function; |
| 2025 | 2030 |
| 2026 Handle<JSFunction> function(raw_function); | 2031 Handle<JSFunction> function(raw_function, isolate); |
| 2027 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2032 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
| 2028 return *function; | 2033 return *function; |
| 2029 } | 2034 } |
| 2030 | 2035 |
| 2031 | 2036 |
| 2032 // Used from ic-<arch>.cc. | 2037 // Used from ic-<arch>.cc. |
| 2033 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 2038 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
| 2034 HandleScope scope(isolate); | 2039 HandleScope scope(isolate); |
| 2035 ASSERT(args.length() == 2); | 2040 ASSERT(args.length() == 2); |
| 2036 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2041 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2661 HandleScope scope(isolate()); | 2666 HandleScope scope(isolate()); |
| 2662 State previous_left, previous_right, previous_state; | 2667 State previous_left, previous_right, previous_state; |
| 2663 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2668 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
| 2664 &previous_right, &previous_state, NULL); | 2669 &previous_right, &previous_state, NULL); |
| 2665 State new_left = InputState(previous_left, x); | 2670 State new_left = InputState(previous_left, x); |
| 2666 State new_right = InputState(previous_right, y); | 2671 State new_right = InputState(previous_right, y); |
| 2667 State state = TargetState(previous_state, previous_left, previous_right, | 2672 State state = TargetState(previous_state, previous_left, previous_right, |
| 2668 HasInlinedSmiCode(address()), x, y); | 2673 HasInlinedSmiCode(address()), x, y); |
| 2669 ICCompareStub stub(op_, new_left, new_right, state); | 2674 ICCompareStub stub(op_, new_left, new_right, state); |
| 2670 if (state == KNOWN_OBJECT) { | 2675 if (state == KNOWN_OBJECT) { |
| 2671 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); | 2676 stub.set_known_map( |
| 2677 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); |
| 2672 } | 2678 } |
| 2673 set_target(*stub.GetCode(isolate())); | 2679 set_target(*stub.GetCode(isolate())); |
| 2674 | 2680 |
| 2675 #ifdef DEBUG | 2681 #ifdef DEBUG |
| 2676 if (FLAG_trace_ic) { | 2682 if (FLAG_trace_ic) { |
| 2677 PrintF("[CompareIC in "); | 2683 PrintF("[CompareIC in "); |
| 2678 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2684 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2679 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 2685 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
| 2680 GetStateName(previous_left), | 2686 GetStateName(previous_left), |
| 2681 GetStateName(previous_right), | 2687 GetStateName(previous_right), |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2737 #undef ADDR | 2743 #undef ADDR |
| 2738 }; | 2744 }; |
| 2739 | 2745 |
| 2740 | 2746 |
| 2741 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2747 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2742 return IC_utilities[id]; | 2748 return IC_utilities[id]; |
| 2743 } | 2749 } |
| 2744 | 2750 |
| 2745 | 2751 |
| 2746 } } // namespace v8::internal | 2752 } } // namespace v8::internal |
| OLD | NEW |