Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 // Change the receiver to the result of calling ToObject on it. | 475 // Change the receiver to the result of calling ToObject on it. |
| 476 const int argc = this->target()->arguments_count(); | 476 const int argc = this->target()->arguments_count(); |
| 477 StackFrameLocator locator; | 477 StackFrameLocator locator; |
| 478 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 478 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| 479 int index = frame->ComputeExpressionsCount() - (argc + 1); | 479 int index = frame->ComputeExpressionsCount() - (argc + 1); |
| 480 frame->SetExpression(index, *Factory::ToObject(object)); | 480 frame->SetExpression(index, *Factory::ToObject(object)); |
| 481 } | 481 } |
| 482 | 482 |
| 483 | 483 |
| 484 MaybeObject* CallICBase::LoadFunction(State state, | 484 MaybeObject* CallICBase::LoadFunction(State state, |
| 485 Code::ExtraICState extra_ic_state, | |
| 485 Handle<Object> object, | 486 Handle<Object> object, |
| 486 Handle<String> name) { | 487 Handle<String> name) { |
| 487 // If the object is undefined or null it's illegal to try to get any | 488 // If the object is undefined or null it's illegal to try to get any |
| 488 // of its properties; throw a TypeError in that case. | 489 // of its properties; throw a TypeError in that case. |
| 489 if (object->IsUndefined() || object->IsNull()) { | 490 if (object->IsUndefined() || object->IsNull()) { |
| 490 return TypeError("non_object_property_call", object, name); | 491 return TypeError("non_object_property_call", object, name); |
| 491 } | 492 } |
| 492 | 493 |
| 493 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 494 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
| 494 ReceiverToObject(object); | 495 ReceiverToObject(object); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 520 // If the object does not have the requested property, check which | 521 // If the object does not have the requested property, check which |
| 521 // exception we need to throw. | 522 // exception we need to throw. |
| 522 if (IsContextual(object)) { | 523 if (IsContextual(object)) { |
| 523 return ReferenceError("not_defined", name); | 524 return ReferenceError("not_defined", name); |
| 524 } | 525 } |
| 525 return TypeError("undefined_method", object, name); | 526 return TypeError("undefined_method", object, name); |
| 526 } | 527 } |
| 527 | 528 |
| 528 // Lookup is valid: Update inline cache and stub cache. | 529 // Lookup is valid: Update inline cache and stub cache. |
| 529 if (FLAG_use_ic) { | 530 if (FLAG_use_ic) { |
| 530 UpdateCaches(&lookup, state, object, name); | 531 UpdateCaches(&lookup, state, extra_ic_state, object, name); |
| 531 } | 532 } |
| 532 | 533 |
| 533 // Get the property. | 534 // Get the property. |
| 534 PropertyAttributes attr; | 535 PropertyAttributes attr; |
| 535 Object* result; | 536 Object* result; |
| 536 { MaybeObject* maybe_result = | 537 { MaybeObject* maybe_result = |
| 537 object->GetProperty(*object, &lookup, *name, &attr); | 538 object->GetProperty(*object, &lookup, *name, &attr); |
| 538 if (!maybe_result->ToObject(&result)) return maybe_result; | 539 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 539 } | 540 } |
| 540 if (lookup.type() == INTERCEPTOR) { | 541 if (lookup.type() == INTERCEPTOR) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 571 MaybeObject* answer = result; | 572 MaybeObject* answer = result; |
| 572 if (!result->IsJSFunction()) { | 573 if (!result->IsJSFunction()) { |
| 573 answer = TypeError("property_not_function", object, name); | 574 answer = TypeError("property_not_function", object, name); |
| 574 } | 575 } |
| 575 return answer; | 576 return answer; |
| 576 } | 577 } |
| 577 | 578 |
| 578 | 579 |
| 579 void CallICBase::UpdateCaches(LookupResult* lookup, | 580 void CallICBase::UpdateCaches(LookupResult* lookup, |
| 580 State state, | 581 State state, |
| 582 Code::ExtraICState extra_ic_state, | |
| 581 Handle<Object> object, | 583 Handle<Object> object, |
| 582 Handle<String> name) { | 584 Handle<String> name) { |
| 583 // Bail out if we didn't find a result. | 585 // Bail out if we didn't find a result. |
| 584 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 586 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| 585 | 587 |
| 586 if (lookup->holder() != *object && | 588 if (lookup->holder() != *object && |
| 587 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) { | 589 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) { |
| 588 // Suppress optimization for prototype chains with slow properties objects | 590 // Suppress optimization for prototype chains with slow properties objects |
| 589 // in the middle. | 591 // in the middle. |
| 590 return; | 592 return; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 617 break; | 619 break; |
| 618 } | 620 } |
| 619 case CONSTANT_FUNCTION: { | 621 case CONSTANT_FUNCTION: { |
| 620 // Get the constant function and compute the code stub for this | 622 // Get the constant function and compute the code stub for this |
| 621 // call; used for rewriting to monomorphic state and making sure | 623 // call; used for rewriting to monomorphic state and making sure |
| 622 // that the code stub is in the stub cache. | 624 // that the code stub is in the stub cache. |
| 623 JSFunction* function = lookup->GetConstantFunction(); | 625 JSFunction* function = lookup->GetConstantFunction(); |
| 624 maybe_code = StubCache::ComputeCallConstant(argc, | 626 maybe_code = StubCache::ComputeCallConstant(argc, |
| 625 in_loop, | 627 in_loop, |
| 626 kind_, | 628 kind_, |
| 629 extra_ic_state, | |
| 627 *name, | 630 *name, |
| 628 *object, | 631 *object, |
| 629 lookup->holder(), | 632 lookup->holder(), |
| 630 function); | 633 function); |
| 631 break; | 634 break; |
| 632 } | 635 } |
| 633 case NORMAL: { | 636 case NORMAL: { |
| 634 if (!object->IsJSObject()) return; | 637 if (!object->IsJSObject()) return; |
| 635 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 638 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 636 | 639 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 700 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 703 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
| 701 name, state, target(), in_loop ? " (in-loop)" : ""); | 704 name, state, target(), in_loop ? " (in-loop)" : ""); |
| 702 #endif | 705 #endif |
| 703 } | 706 } |
| 704 | 707 |
| 705 | 708 |
| 706 MaybeObject* KeyedCallIC::LoadFunction(State state, | 709 MaybeObject* KeyedCallIC::LoadFunction(State state, |
| 707 Handle<Object> object, | 710 Handle<Object> object, |
| 708 Handle<Object> key) { | 711 Handle<Object> key) { |
| 709 if (key->IsSymbol()) { | 712 if (key->IsSymbol()) { |
| 710 return CallICBase::LoadFunction(state, object, Handle<String>::cast(key)); | 713 return CallICBase::LoadFunction(state, |
| 714 Code::kNoExtraICState, | |
| 715 object, | |
| 716 Handle<String>::cast(key)); | |
| 711 } | 717 } |
| 712 | 718 |
| 713 if (object->IsUndefined() || object->IsNull()) { | 719 if (object->IsUndefined() || object->IsNull()) { |
| 714 return TypeError("non_object_property_call", object, key); | 720 return TypeError("non_object_property_call", object, key); |
| 715 } | 721 } |
| 716 | 722 |
| 717 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 723 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
| 718 ReceiverToObject(object); | 724 ReceiverToObject(object); |
| 719 } | 725 } |
| 720 | 726 |
| (...skipping 910 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1631 } else { | 1637 } else { |
| 1632 CompileLazy(function_handle, CLEAR_EXCEPTION); | 1638 CompileLazy(function_handle, CLEAR_EXCEPTION); |
| 1633 } | 1639 } |
| 1634 return *function_handle; | 1640 return *function_handle; |
| 1635 } | 1641 } |
| 1636 | 1642 |
| 1637 | 1643 |
| 1638 // Used from ic-<arch>.cc. | 1644 // Used from ic-<arch>.cc. |
| 1639 MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { | 1645 MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { |
| 1640 NoHandleAllocation na; | 1646 NoHandleAllocation na; |
| 1641 ASSERT(args.length() == 2); | 1647 ASSERT(args.length() == 2 || args.length() == 3); |
| 1642 CallIC ic; | 1648 CallIC ic; |
| 1643 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1649 IC::State state; |
| 1650 Code::ExtraICState extra_ic_state; | |
| 1651 if (args.length() == 2) { | |
|
Mads Ager (chromium)
2011/01/17 14:06:00
As discussed offline I would like to keep all the
| |
| 1652 state = IC::StateFrom(ic.target(), args[0], args[1]); | |
| 1653 extra_ic_state = Code::kNoExtraICState; | |
| 1654 } else { | |
| 1655 ASSERT(args.length() == 3); | |
| 1656 ASSERT(ic.target()->ic_state() == MONOMORPHIC); | |
| 1657 // Extra IC state change is requested. Use PREMONOMORPHIC to | |
| 1658 // trigger generating a new stub. | |
| 1659 state = PREMONOMORPHIC; | |
| 1660 extra_ic_state = static_cast<Code::ExtraICState>( | |
| 1661 Smi::cast(args[2])->value()); | |
| 1662 } | |
| 1663 MaybeObject* maybe_result = ic.LoadFunction(state, | |
| 1664 extra_ic_state, | |
| 1665 args.at<Object>(0), | |
| 1666 args.at<String>(1)); | |
| 1644 Object* result; | 1667 Object* result; |
| 1645 { MaybeObject* maybe_result = | 1668 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1646 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); | |
| 1647 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1648 } | |
| 1649 | 1669 |
| 1650 // The first time the inline cache is updated may be the first time the | 1670 // The first time the inline cache is updated may be the first time the |
| 1651 // function it references gets called. If the function was lazily compiled | 1671 // function it references gets called. If the function was lazily compiled |
| 1652 // then the first call will trigger a compilation. We check for this case | 1672 // then the first call will trigger a compilation. We check for this case |
| 1653 // and we do the compilation immediately, instead of waiting for the stub | 1673 // and we do the compilation immediately, instead of waiting for the stub |
| 1654 // currently attached to the JSFunction object to trigger compilation. We | 1674 // currently attached to the JSFunction object to trigger compilation. We |
| 1655 // do this in the case where we know that the inline cache is inside a loop, | 1675 // do this in the case where we know that the inline cache is inside a loop, |
| 1656 // because then we know that we want to optimize the function. | 1676 // because then we know that we want to optimize the function. |
| 1657 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1677 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
| 1658 return result; | 1678 return result; |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2164 #undef ADDR | 2184 #undef ADDR |
| 2165 }; | 2185 }; |
| 2166 | 2186 |
| 2167 | 2187 |
| 2168 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2188 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2169 return IC_utilities[id]; | 2189 return IC_utilities[id]; |
| 2170 } | 2190 } |
| 2171 | 2191 |
| 2172 | 2192 |
| 2173 } } // namespace v8::internal | 2193 } } // namespace v8::internal |
| OLD | NEW |