| 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 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 if (proto->IsNull()) { | 224 if (proto->IsNull()) { |
| 225 ASSERT(!lookup->IsFound()); | 225 ASSERT(!lookup->IsFound()); |
| 226 return; | 226 return; |
| 227 } | 227 } |
| 228 | 228 |
| 229 object = proto; | 229 object = proto; |
| 230 } | 230 } |
| 231 } | 231 } |
| 232 | 232 |
| 233 | 233 |
| 234 bool CallIC::TryUpdateExtraICState(LookupResult* lookup, | |
| 235 Handle<Object> object) { | |
| 236 if (!lookup->IsConstantFunction()) return false; | |
| 237 JSFunction* function = lookup->GetConstantFunction(); | |
| 238 if (!function->shared()->HasBuiltinFunctionId()) return false; | |
| 239 | |
| 240 // Fetch the arguments passed to the called function. | |
| 241 const int argc = target()->arguments_count(); | |
| 242 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top()); | |
| 243 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | |
| 244 Arguments args(argc + 1, | |
| 245 &Memory::Object_at(fp + | |
| 246 StandardFrameConstants::kCallerSPOffset + | |
| 247 argc * kPointerSize)); | |
| 248 switch (function->shared()->builtin_function_id()) { | |
| 249 case kStringCharCodeAt: | |
| 250 case kStringCharAt: | |
| 251 if (object->IsString()) { | |
| 252 String* string = String::cast(*object); | |
| 253 // Check there's the right string value or wrapper in the receiver slot. | |
| 254 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); | |
| 255 // If we're in the default (fastest) state and the index is | |
| 256 // out of bounds, update the state to record this fact. | |
| 257 if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB && | |
| 258 argc >= 1 && args[1]->IsNumber()) { | |
| 259 double index = DoubleToInteger(args.number_at(1)); | |
| 260 if (index < 0 || index >= string->length()) { | |
| 261 set_extra_ic_state(StringStubState::update(extra_ic_state(), | |
| 262 STRING_INDEX_OUT_OF_BOUNDS)); | |
| 263 return true; | |
| 264 } | |
| 265 } | |
| 266 } | |
| 267 break; | |
| 268 default: | |
| 269 return false; | |
| 270 } | |
| 271 return false; | |
| 272 } | |
| 273 | |
| 274 | |
| 275 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 234 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
| 276 Handle<String> name) { | 235 Handle<String> name) { |
| 277 if (target()->is_call_stub()) { | |
| 278 LookupResult lookup(isolate()); | |
| 279 LookupForRead(receiver, name, &lookup); | |
| 280 if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) { | |
| 281 return true; | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 if (target()->is_keyed_stub()) { | 236 if (target()->is_keyed_stub()) { |
| 286 // Determine whether the failure is due to a name failure. | 237 // Determine whether the failure is due to a name failure. |
| 287 if (!name->IsName()) return false; | 238 if (!name->IsName()) return false; |
| 288 Name* stub_name = target()->FindFirstName(); | 239 Name* stub_name = target()->FindFirstName(); |
| 289 if (*name != stub_name) return false; | 240 if (*name != stub_name) return false; |
| 290 } | 241 } |
| 291 | 242 |
| 292 InlineCacheHolderFlag cache_holder = | 243 InlineCacheHolderFlag cache_holder = |
| 293 Code::ExtractCacheHolderFromFlags(target()->flags()); | 244 Code::ExtractCacheHolderFromFlags(target()->flags()); |
| 294 | 245 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 // Otherwise, it will fail in the lookup step. | 570 // Otherwise, it will fail in the lookup step. |
| 620 } | 571 } |
| 621 | 572 |
| 622 // Lookup the property in the object. | 573 // Lookup the property in the object. |
| 623 LookupResult lookup(isolate()); | 574 LookupResult lookup(isolate()); |
| 624 LookupForRead(object, name, &lookup); | 575 LookupForRead(object, name, &lookup); |
| 625 | 576 |
| 626 if (!lookup.IsFound()) { | 577 if (!lookup.IsFound()) { |
| 627 // If the object does not have the requested property, check which | 578 // If the object does not have the requested property, check which |
| 628 // exception we need to throw. | 579 // exception we need to throw. |
| 629 return IsUndeclaredGlobal(object) | 580 return object->IsGlobalObject() |
| 630 ? ReferenceError("not_defined", name) | 581 ? ReferenceError("not_defined", name) |
| 631 : TypeError("undefined_method", object, name); | 582 : TypeError("undefined_method", object, name); |
| 632 } | 583 } |
| 633 | 584 |
| 634 // Lookup is valid: Update inline cache and stub cache. | 585 // Lookup is valid: Update inline cache and stub cache. |
| 635 if (use_ic) UpdateCaches(&lookup, object, name); | 586 if (use_ic) UpdateCaches(&lookup, object, name); |
| 636 | 587 |
| 637 // Get the property. | 588 // Get the property. |
| 638 PropertyAttributes attr; | 589 PropertyAttributes attr; |
| 639 Handle<Object> result = | 590 Handle<Object> result = |
| 640 Object::GetProperty(object, object, &lookup, name, &attr); | 591 Object::GetProperty(object, object, &lookup, name, &attr); |
| 641 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 592 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 642 | 593 |
| 643 if (lookup.IsInterceptor() && attr == ABSENT) { | 594 if (lookup.IsInterceptor() && attr == ABSENT) { |
| 644 // If the object does not have the requested property, check which | 595 // If the object does not have the requested property, check which |
| 645 // exception we need to throw. | 596 // exception we need to throw. |
| 646 return IsUndeclaredGlobal(object) | 597 return object->IsGlobalObject() |
| 647 ? ReferenceError("not_defined", name) | 598 ? ReferenceError("not_defined", name) |
| 648 : TypeError("undefined_method", object, name); | 599 : TypeError("undefined_method", object, name); |
| 649 } | 600 } |
| 650 | 601 |
| 651 ASSERT(!result->IsTheHole()); | 602 ASSERT(!result->IsTheHole()); |
| 652 | 603 |
| 653 // Make receiver an object if the callee requires it. Strict mode or builtin | 604 // 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 | 605 // functions do not wrap the receiver, non-strict functions and objects |
| 655 // called as functions do. | 606 // called as functions do. |
| 656 ReceiverToObjectIfRequired(result, object); | 607 ReceiverToObjectIfRequired(result, object); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 break; | 1046 break; |
| 1096 case GENERIC: | 1047 case GENERIC: |
| 1097 UNREACHABLE(); | 1048 UNREACHABLE(); |
| 1098 break; | 1049 break; |
| 1099 } | 1050 } |
| 1100 } | 1051 } |
| 1101 | 1052 |
| 1102 | 1053 |
| 1103 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { | 1054 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { |
| 1104 Handle<Code> ic = isolate->stub_cache()->ComputeLoad( | 1055 Handle<Code> ic = isolate->stub_cache()->ComputeLoad( |
| 1105 UNINITIALIZED, IC::ComputeExtraICState(mode)); | 1056 UNINITIALIZED, ComputeExtraICState(mode)); |
| 1106 return ic; | 1057 return ic; |
| 1107 } | 1058 } |
| 1108 | 1059 |
| 1109 | 1060 |
| 1110 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 1061 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
| 1111 ContextualMode mode) { | 1062 ContextualMode mode) { |
| 1112 return isolate->stub_cache()->ComputeLoad( | 1063 return isolate->stub_cache()->ComputeLoad( |
| 1113 PREMONOMORPHIC, IC::ComputeExtraICState(mode)); | 1064 PREMONOMORPHIC, ComputeExtraICState(mode)); |
| 1114 } | 1065 } |
| 1115 | 1066 |
| 1116 | 1067 |
| 1117 Handle<Code> LoadIC::megamorphic_stub() { | 1068 Handle<Code> LoadIC::megamorphic_stub() { |
| 1118 return isolate()->stub_cache()->ComputeLoad( | 1069 return isolate()->stub_cache()->ComputeLoad( |
| 1119 MEGAMORPHIC, extra_ic_state()); | 1070 MEGAMORPHIC, extra_ic_state()); |
| 1120 } | 1071 } |
| 1121 | 1072 |
| 1122 | 1073 |
| 1123 Handle<Code> LoadIC::SimpleFieldLoad(int offset, | 1074 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); | 1514 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1564 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1515 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1565 return *result; | 1516 return *result; |
| 1566 } | 1517 } |
| 1567 | 1518 |
| 1568 LookupResult lookup(isolate()); | 1519 LookupResult lookup(isolate()); |
| 1569 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); | 1520 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); |
| 1570 if (!can_store && | 1521 if (!can_store && |
| 1571 strict_mode() == kStrictMode && | 1522 strict_mode() == kStrictMode && |
| 1572 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1523 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1573 IsUndeclaredGlobal(object)) { | 1524 object->IsGlobalObject()) { |
| 1574 // Strict mode doesn't allow setting non-existent global property. | 1525 // Strict mode doesn't allow setting non-existent global property. |
| 1575 return ReferenceError("not_defined", name); | 1526 return ReferenceError("not_defined", name); |
| 1576 } | 1527 } |
| 1577 if (FLAG_use_ic) { | 1528 if (FLAG_use_ic) { |
| 1578 if (state() == UNINITIALIZED) { | 1529 if (state() == UNINITIALIZED) { |
| 1579 Handle<Code> stub = pre_monomorphic_stub(); | 1530 Handle<Code> stub = pre_monomorphic_stub(); |
| 1580 set_target(*stub); | 1531 set_target(*stub); |
| 1581 TRACE_IC("StoreIC", name); | 1532 TRACE_IC("StoreIC", name); |
| 1582 } else if (can_store) { | 1533 } else if (can_store) { |
| 1583 UpdateCaches(&lookup, receiver, name, value); | 1534 UpdateCaches(&lookup, receiver, name, value); |
| 1584 } else if (!name->IsCacheable(isolate()) || | 1535 } else if (!name->IsCacheable(isolate()) || |
| 1585 lookup.IsNormal() || | 1536 lookup.IsNormal() || |
| 1586 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1537 (lookup.IsField() && lookup.CanHoldValue(value))) { |
| 1587 Handle<Code> stub = generic_stub(); | 1538 Handle<Code> stub = generic_stub(); |
| 1588 set_target(*stub); | 1539 set_target(*stub); |
| 1589 } | 1540 } |
| 1590 } | 1541 } |
| 1591 | 1542 |
| 1592 // Set the property. | 1543 // Set the property. |
| 1593 Handle<Object> result = JSReceiver::SetProperty( | 1544 Handle<Object> result = JSReceiver::SetProperty( |
| 1594 receiver, name, value, NONE, strict_mode(), store_mode); | 1545 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1595 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1546 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1596 return *result; | 1547 return *result; |
| 1597 } | 1548 } |
| 1598 | 1549 |
| 1599 | 1550 |
| 1600 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1551 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
| 1601 StrictModeFlag strict_mode, | 1552 StrictModeFlag strict_mode) { |
| 1602 ContextualMode mode) { | 1553 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
| 1603 ExtraICState extra_state = ComputeExtraICState(strict_mode, mode); | |
| 1604 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1554 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
| 1605 UNINITIALIZED, extra_state); | 1555 UNINITIALIZED, extra_state); |
| 1606 return ic; | 1556 return ic; |
| 1607 } | 1557 } |
| 1608 | 1558 |
| 1609 | 1559 |
| 1610 Handle<Code> StoreIC::megamorphic_stub() { | 1560 Handle<Code> StoreIC::megamorphic_stub() { |
| 1611 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); | 1561 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); |
| 1612 } | 1562 } |
| 1613 | 1563 |
| 1614 | 1564 |
| 1615 Handle<Code> StoreIC::generic_stub() const { | 1565 Handle<Code> StoreIC::generic_stub() const { |
| 1616 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); | 1566 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); |
| 1617 } | 1567 } |
| 1618 | 1568 |
| 1619 | 1569 |
| 1620 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, | 1570 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, |
| 1621 StrictModeFlag strict_mode, | 1571 StrictModeFlag strict_mode) { |
| 1622 ContextualMode contextual_mode) { | 1572 ExtraICState state = ComputeExtraICState(strict_mode); |
| 1623 ExtraICState state = StoreIC::ComputeExtraICState(strict_mode, | |
| 1624 contextual_mode); | |
| 1625 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); | 1573 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); |
| 1626 } | 1574 } |
| 1627 | 1575 |
| 1628 | 1576 |
| 1629 void StoreIC::UpdateCaches(LookupResult* lookup, | 1577 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1630 Handle<JSObject> receiver, | 1578 Handle<JSObject> receiver, |
| 1631 Handle<String> name, | 1579 Handle<String> name, |
| 1632 Handle<Object> value) { | 1580 Handle<Object> value) { |
| 1633 ASSERT(lookup->IsFound()); | 1581 ASSERT(lookup->IsFound()); |
| 1634 | 1582 |
| (...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3221 #undef ADDR | 3169 #undef ADDR |
| 3222 }; | 3170 }; |
| 3223 | 3171 |
| 3224 | 3172 |
| 3225 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3173 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3226 return IC_utilities[id]; | 3174 return IC_utilities[id]; |
| 3227 } | 3175 } |
| 3228 | 3176 |
| 3229 | 3177 |
| 3230 } } // namespace v8::internal | 3178 } } // namespace v8::internal |
| OLD | NEW |