| 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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 // Return the address in the original code. This is the place where | 178 // Return the address in the original code. This is the place where |
| 179 // the call which has been overwritten by the DebugBreakXXX resides | 179 // the call which has been overwritten by the DebugBreakXXX resides |
| 180 // and the place where the inline cache system should look. | 180 // and the place where the inline cache system should look. |
| 181 intptr_t delta = | 181 intptr_t delta = |
| 182 original_code->instruction_start() - code->instruction_start(); | 182 original_code->instruction_start() - code->instruction_start(); |
| 183 return addr + delta; | 183 return addr + delta; |
| 184 } | 184 } |
| 185 #endif | 185 #endif |
| 186 | 186 |
| 187 | 187 |
| 188 bool IC::IsContextualLoad() const { |
| 189 if (IsLoadStub()) { |
| 190 return LoadIC::GetContextualMode(extra_ic_state()) == CONTEXTUAL; |
| 191 } |
| 192 return false; |
| 193 } |
| 194 |
| 195 |
| 188 static bool HasInterceptorGetter(JSObject* object) { | 196 static bool HasInterceptorGetter(JSObject* object) { |
| 189 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 197 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
| 190 } | 198 } |
| 191 | 199 |
| 192 | 200 |
| 193 static bool HasInterceptorSetter(JSObject* object) { | 201 static bool HasInterceptorSetter(JSObject* object) { |
| 194 return !object->GetNamedInterceptor()->setter()->IsUndefined(); | 202 return !object->GetNamedInterceptor()->setter()->IsUndefined(); |
| 195 } | 203 } |
| 196 | 204 |
| 197 | 205 |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 // Otherwise, it will fail in the lookup step. | 627 // Otherwise, it will fail in the lookup step. |
| 620 } | 628 } |
| 621 | 629 |
| 622 // Lookup the property in the object. | 630 // Lookup the property in the object. |
| 623 LookupResult lookup(isolate()); | 631 LookupResult lookup(isolate()); |
| 624 LookupForRead(object, name, &lookup); | 632 LookupForRead(object, name, &lookup); |
| 625 | 633 |
| 626 if (!lookup.IsFound()) { | 634 if (!lookup.IsFound()) { |
| 627 // If the object does not have the requested property, check which | 635 // If the object does not have the requested property, check which |
| 628 // exception we need to throw. | 636 // exception we need to throw. |
| 629 return IsUndeclaredGlobal(object) | 637 return object->IsGlobalObject() |
| 630 ? ReferenceError("not_defined", name) | 638 ? ReferenceError("not_defined", name) |
| 631 : TypeError("undefined_method", object, name); | 639 : TypeError("undefined_method", object, name); |
| 632 } | 640 } |
| 633 | 641 |
| 634 // Lookup is valid: Update inline cache and stub cache. | 642 // Lookup is valid: Update inline cache and stub cache. |
| 635 if (use_ic) UpdateCaches(&lookup, object, name); | 643 if (use_ic) UpdateCaches(&lookup, object, name); |
| 636 | 644 |
| 637 // Get the property. | 645 // Get the property. |
| 638 PropertyAttributes attr; | 646 PropertyAttributes attr; |
| 639 Handle<Object> result = | 647 Handle<Object> result = |
| 640 Object::GetProperty(object, object, &lookup, name, &attr); | 648 Object::GetProperty(object, object, &lookup, name, &attr); |
| 641 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 649 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 642 | 650 |
| 643 if (lookup.IsInterceptor() && attr == ABSENT) { | 651 if (lookup.IsInterceptor() && attr == ABSENT) { |
| 644 // If the object does not have the requested property, check which | 652 // If the object does not have the requested property, check which |
| 645 // exception we need to throw. | 653 // exception we need to throw. |
| 646 return IsUndeclaredGlobal(object) | 654 return object->IsGlobalObject() |
| 647 ? ReferenceError("not_defined", name) | 655 ? ReferenceError("not_defined", name) |
| 648 : TypeError("undefined_method", object, name); | 656 : TypeError("undefined_method", object, name); |
| 649 } | 657 } |
| 650 | 658 |
| 651 ASSERT(!result->IsTheHole()); | 659 ASSERT(!result->IsTheHole()); |
| 652 | 660 |
| 653 // Make receiver an object if the callee requires it. Strict mode or builtin | 661 // Make receiver an object if the callee requires it. Strict mode or builtin |
| 654 // functions do not wrap the receiver, non-strict functions and objects | 662 // functions do not wrap the receiver, non-strict functions and objects |
| 655 // called as functions do. | 663 // called as functions do. |
| 656 ReceiverToObjectIfRequired(result, object); | 664 ReceiverToObjectIfRequired(result, object); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 break; | 1103 break; |
| 1096 case GENERIC: | 1104 case GENERIC: |
| 1097 UNREACHABLE(); | 1105 UNREACHABLE(); |
| 1098 break; | 1106 break; |
| 1099 } | 1107 } |
| 1100 } | 1108 } |
| 1101 | 1109 |
| 1102 | 1110 |
| 1103 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { | 1111 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { |
| 1104 Handle<Code> ic = isolate->stub_cache()->ComputeLoad( | 1112 Handle<Code> ic = isolate->stub_cache()->ComputeLoad( |
| 1105 UNINITIALIZED, IC::ComputeExtraICState(mode)); | 1113 UNINITIALIZED, LoadIC::ComputeExtraICState(mode)); |
| 1106 return ic; | 1114 return ic; |
| 1107 } | 1115 } |
| 1108 | 1116 |
| 1109 | 1117 |
| 1110 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 1118 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
| 1111 ContextualMode mode) { | 1119 ContextualMode mode) { |
| 1112 return isolate->stub_cache()->ComputeLoad( | 1120 return isolate->stub_cache()->ComputeLoad( |
| 1113 PREMONOMORPHIC, IC::ComputeExtraICState(mode)); | 1121 PREMONOMORPHIC, LoadIC::ComputeExtraICState(mode)); |
| 1114 } | 1122 } |
| 1115 | 1123 |
| 1116 | 1124 |
| 1117 Handle<Code> LoadIC::megamorphic_stub() { | 1125 Handle<Code> LoadIC::megamorphic_stub() { |
| 1118 return isolate()->stub_cache()->ComputeLoad( | 1126 return isolate()->stub_cache()->ComputeLoad( |
| 1119 MEGAMORPHIC, extra_ic_state()); | 1127 MEGAMORPHIC, extra_ic_state()); |
| 1120 } | 1128 } |
| 1121 | 1129 |
| 1122 | 1130 |
| 1123 Handle<Code> LoadIC::SimpleFieldLoad(int offset, | 1131 Handle<Code> LoadIC::SimpleFieldLoad(int offset, |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1563 receiver, name, value, NONE, strict_mode(), store_mode); | 1571 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1564 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1572 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1565 return *result; | 1573 return *result; |
| 1566 } | 1574 } |
| 1567 | 1575 |
| 1568 LookupResult lookup(isolate()); | 1576 LookupResult lookup(isolate()); |
| 1569 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); | 1577 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); |
| 1570 if (!can_store && | 1578 if (!can_store && |
| 1571 strict_mode() == kStrictMode && | 1579 strict_mode() == kStrictMode && |
| 1572 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1580 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1573 IsUndeclaredGlobal(object)) { | 1581 object->IsGlobalObject()) { |
| 1574 // Strict mode doesn't allow setting non-existent global property. | 1582 // Strict mode doesn't allow setting non-existent global property. |
| 1575 return ReferenceError("not_defined", name); | 1583 return ReferenceError("not_defined", name); |
| 1576 } | 1584 } |
| 1577 if (FLAG_use_ic) { | 1585 if (FLAG_use_ic) { |
| 1578 if (state() == UNINITIALIZED) { | 1586 if (state() == UNINITIALIZED) { |
| 1579 Handle<Code> stub = pre_monomorphic_stub(); | 1587 Handle<Code> stub = pre_monomorphic_stub(); |
| 1580 set_target(*stub); | 1588 set_target(*stub); |
| 1581 TRACE_IC("StoreIC", name); | 1589 TRACE_IC("StoreIC", name); |
| 1582 } else if (can_store) { | 1590 } else if (can_store) { |
| 1583 UpdateCaches(&lookup, receiver, name, value); | 1591 UpdateCaches(&lookup, receiver, name, value); |
| 1584 } else if (!name->IsCacheable(isolate()) || | 1592 } else if (!name->IsCacheable(isolate()) || |
| 1585 lookup.IsNormal() || | 1593 lookup.IsNormal() || |
| 1586 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1594 (lookup.IsField() && lookup.CanHoldValue(value))) { |
| 1587 Handle<Code> stub = generic_stub(); | 1595 Handle<Code> stub = generic_stub(); |
| 1588 set_target(*stub); | 1596 set_target(*stub); |
| 1589 } | 1597 } |
| 1590 } | 1598 } |
| 1591 | 1599 |
| 1592 // Set the property. | 1600 // Set the property. |
| 1593 Handle<Object> result = JSReceiver::SetProperty( | 1601 Handle<Object> result = JSReceiver::SetProperty( |
| 1594 receiver, name, value, NONE, strict_mode(), store_mode); | 1602 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1595 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1603 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1596 return *result; | 1604 return *result; |
| 1597 } | 1605 } |
| 1598 | 1606 |
| 1599 | 1607 |
| 1600 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1608 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
| 1601 StrictModeFlag strict_mode, | 1609 StrictModeFlag strict_mode) { |
| 1602 ContextualMode mode) { | 1610 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
| 1603 ExtraICState extra_state = ComputeExtraICState(strict_mode, mode); | |
| 1604 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1611 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
| 1605 UNINITIALIZED, extra_state); | 1612 UNINITIALIZED, extra_state); |
| 1606 return ic; | 1613 return ic; |
| 1607 } | 1614 } |
| 1608 | 1615 |
| 1609 | 1616 |
| 1610 Handle<Code> StoreIC::megamorphic_stub() { | 1617 Handle<Code> StoreIC::megamorphic_stub() { |
| 1611 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); | 1618 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); |
| 1612 } | 1619 } |
| 1613 | 1620 |
| 1614 | 1621 |
| 1615 Handle<Code> StoreIC::generic_stub() const { | 1622 Handle<Code> StoreIC::generic_stub() const { |
| 1616 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); | 1623 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); |
| 1617 } | 1624 } |
| 1618 | 1625 |
| 1619 | 1626 |
| 1620 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, | 1627 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, |
| 1621 StrictModeFlag strict_mode, | 1628 StrictModeFlag strict_mode) { |
| 1622 ContextualMode contextual_mode) { | 1629 ExtraICState state = StoreIC::ComputeExtraICState(strict_mode); |
| 1623 ExtraICState state = StoreIC::ComputeExtraICState(strict_mode, | |
| 1624 contextual_mode); | |
| 1625 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); | 1630 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); |
| 1626 } | 1631 } |
| 1627 | 1632 |
| 1628 | 1633 |
| 1629 void StoreIC::UpdateCaches(LookupResult* lookup, | 1634 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1630 Handle<JSObject> receiver, | 1635 Handle<JSObject> receiver, |
| 1631 Handle<String> name, | 1636 Handle<String> name, |
| 1632 Handle<Object> value) { | 1637 Handle<Object> value) { |
| 1633 ASSERT(lookup->IsFound()); | 1638 ASSERT(lookup->IsFound()); |
| 1634 | 1639 |
| (...skipping 1585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3220 #undef ADDR | 3225 #undef ADDR |
| 3221 }; | 3226 }; |
| 3222 | 3227 |
| 3223 | 3228 |
| 3224 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3229 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3225 return IC_utilities[id]; | 3230 return IC_utilities[id]; |
| 3226 } | 3231 } |
| 3227 | 3232 |
| 3228 | 3233 |
| 3229 } } // namespace v8::internal | 3234 } } // namespace v8::internal |
| OLD | NEW |