Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: src/ic.cc

Issue 6474026: Strict mode assignment to undefined reference. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix presubmit. Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | src/stub-cache.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // Reset the map check of the inlined inobject property store (if 335 // Reset the map check of the inlined inobject property store (if
336 // present) to guarantee failure by holding an invalid map (the null 336 // present) to guarantee failure by holding an invalid map (the null
337 // value). The offset can be patched to anything. 337 // value). The offset can be patched to anything.
338 PatchInlinedStore(address, Heap::null_value(), 0); 338 PatchInlinedStore(address, Heap::null_value(), 0);
339 } 339 }
340 340
341 341
342 void StoreIC::Clear(Address address, Code* target) { 342 void StoreIC::Clear(Address address, Code* target) {
343 if (target->ic_state() == UNINITIALIZED) return; 343 if (target->ic_state() == UNINITIALIZED) return;
344 ClearInlinedVersion(address); 344 ClearInlinedVersion(address);
345 SetTargetAtAddress(address, initialize_stub()); 345 SetTargetAtAddress(address,
346 target->extra_ic_state() == kStoreICStrict
347 ? initialize_stub_strict()
348 : initialize_stub());
346 } 349 }
347 350
348 351
349 void KeyedStoreIC::ClearInlinedVersion(Address address) { 352 void KeyedStoreIC::ClearInlinedVersion(Address address) {
350 // Insert null as the elements map to check for. This will make 353 // Insert null as the elements map to check for. This will make
351 // sure that the elements fast-case map check fails so that control 354 // sure that the elements fast-case map check fails so that control
352 // flows to the IC instead of the inlined version. 355 // flows to the IC instead of the inlined version.
353 PatchInlinedStore(address, Heap::null_value()); 356 PatchInlinedStore(address, Heap::null_value());
354 } 357 }
355 358
(...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 object->LocalLookupRealNamedProperty(name, lookup); 1364 object->LocalLookupRealNamedProperty(name, lookup);
1362 return StoreICableLookup(lookup); 1365 return StoreICableLookup(lookup);
1363 } 1366 }
1364 } 1367 }
1365 1368
1366 return true; 1369 return true;
1367 } 1370 }
1368 1371
1369 1372
1370 MaybeObject* StoreIC::Store(State state, 1373 MaybeObject* StoreIC::Store(State state,
1374 Code::ExtraICState extra_ic_state,
1371 Handle<Object> object, 1375 Handle<Object> object,
1372 Handle<String> name, 1376 Handle<String> name,
1373 Handle<Object> value) { 1377 Handle<Object> value) {
1374 // If the object is undefined or null it's illegal to try to set any 1378 // If the object is undefined or null it's illegal to try to set any
1375 // properties on it; throw a TypeError in that case. 1379 // properties on it; throw a TypeError in that case.
1376 if (object->IsUndefined() || object->IsNull()) { 1380 if (object->IsUndefined() || object->IsNull()) {
1377 return TypeError("non_object_property_store", object, name); 1381 return TypeError("non_object_property_store", object, name);
1378 } 1382 }
1379 1383
1380 // Ignore stores where the receiver is not a JSObject. 1384 // Ignore stores where the receiver is not a JSObject.
1381 if (!object->IsJSObject()) return *value; 1385 if (!object->IsJSObject()) return *value;
1382 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1386 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1383 1387
1384 // Check if the given name is an array index. 1388 // Check if the given name is an array index.
1385 uint32_t index; 1389 uint32_t index;
1386 if (name->AsArrayIndex(&index)) { 1390 if (name->AsArrayIndex(&index)) {
1387 HandleScope scope; 1391 HandleScope scope;
1388 Handle<Object> result = SetElement(receiver, index, value); 1392 Handle<Object> result = SetElement(receiver, index, value);
1389 if (result.is_null()) return Failure::Exception(); 1393 if (result.is_null()) return Failure::Exception();
1390 return *value; 1394 return *value;
1391 } 1395 }
1392 1396
1393 // Use specialized code for setting the length of arrays. 1397 // Use specialized code for setting the length of arrays.
1394 if (receiver->IsJSArray() 1398 if (receiver->IsJSArray()
1395 && name->Equals(Heap::length_symbol()) 1399 && name->Equals(Heap::length_symbol())
1396 && receiver->AllowsSetElementsLength()) { 1400 && receiver->AllowsSetElementsLength()) {
1397 #ifdef DEBUG 1401 #ifdef DEBUG
1398 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); 1402 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1399 #endif 1403 #endif
1400 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); 1404 Builtins::Name target = (extra_ic_state == kStoreICStrict)
1401 set_target(target); 1405 ? Builtins::StoreIC_ArrayLength_Strict
1406 : Builtins::StoreIC_ArrayLength;
1407 set_target(Builtins::builtin(target));
1402 return receiver->SetProperty(*name, *value, NONE); 1408 return receiver->SetProperty(*name, *value, NONE);
1403 } 1409 }
1404 1410
1405 // Lookup the property locally in the receiver. 1411 // Lookup the property locally in the receiver.
1406 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { 1412 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1407 LookupResult lookup; 1413 LookupResult lookup;
1408 1414
1409 if (LookupForWrite(*receiver, *name, &lookup)) { 1415 if (LookupForWrite(*receiver, *name, &lookup)) {
1410 bool can_be_inlined = 1416 bool can_be_inlined =
1411 state == UNINITIALIZED && 1417 state == UNINITIALIZED &&
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1449 if (FLAG_trace_ic) { 1455 if (FLAG_trace_ic) {
1450 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n", 1456 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n",
1451 *name->ToCString()); 1457 *name->ToCString());
1452 #endif 1458 #endif
1453 } 1459 }
1454 } 1460 }
1455 } 1461 }
1456 1462
1457 // If no inlined store ic was patched, generate a stub for this 1463 // If no inlined store ic was patched, generate a stub for this
1458 // store. 1464 // store.
1459 UpdateCaches(&lookup, state, receiver, name, value); 1465 UpdateCaches(&lookup, state, extra_ic_state, receiver, name, value);
1466 } else {
1467 // Strict mode doesn't allow setting non-existent global property.
1468 if (extra_ic_state == kStoreICStrict && IsContextual(object)) {
1469 return ReferenceError("not_defined", name);
1470 }
1460 } 1471 }
1461 } 1472 }
1462 1473
1463 if (receiver->IsJSGlobalProxy()) { 1474 if (receiver->IsJSGlobalProxy()) {
1464 // Generate a generic stub that goes to the runtime when we see a global 1475 // Generate a generic stub that goes to the runtime when we see a global
1465 // proxy as receiver. 1476 // proxy as receiver.
1466 if (target() != global_proxy_stub()) { 1477 Code* stub = (extra_ic_state == kStoreICStrict)
1467 set_target(global_proxy_stub()); 1478 ? global_proxy_stub_strict()
1479 : global_proxy_stub();
1480 if (target() != stub) {
1481 set_target(stub);
1468 #ifdef DEBUG 1482 #ifdef DEBUG
1469 TraceIC("StoreIC", name, state, target()); 1483 TraceIC("StoreIC", name, state, target());
1470 #endif 1484 #endif
1471 } 1485 }
1472 } 1486 }
1473 1487
1474 // Set the property. 1488 // Set the property.
1475 return receiver->SetProperty(*name, *value, NONE); 1489 return receiver->SetProperty(*name, *value, NONE);
1476 } 1490 }
1477 1491
1478 1492
1479 void StoreIC::UpdateCaches(LookupResult* lookup, 1493 void StoreIC::UpdateCaches(LookupResult* lookup,
1480 State state, 1494 State state,
1495 Code::ExtraICState extra_ic_state,
1481 Handle<JSObject> receiver, 1496 Handle<JSObject> receiver,
1482 Handle<String> name, 1497 Handle<String> name,
1483 Handle<Object> value) { 1498 Handle<Object> value) {
1484 // Skip JSGlobalProxy. 1499 // Skip JSGlobalProxy.
1485 ASSERT(!receiver->IsJSGlobalProxy()); 1500 ASSERT(!receiver->IsJSGlobalProxy());
1486 1501
1487 ASSERT(StoreICableLookup(lookup)); 1502 ASSERT(StoreICableLookup(lookup));
1488 1503
1489 // If the property has a non-field type allowing map transitions 1504 // If the property has a non-field type allowing map transitions
1490 // where there is extra room in the object, we leave the IC in its 1505 // where there is extra room in the object, we leave the IC in its
1491 // current state. 1506 // current state.
1492 PropertyType type = lookup->type(); 1507 PropertyType type = lookup->type();
1493 1508
1494 // Compute the code stub for this store; used for rewriting to 1509 // Compute the code stub for this store; used for rewriting to
1495 // monomorphic state and making sure that the code stub is in the 1510 // monomorphic state and making sure that the code stub is in the
1496 // stub cache. 1511 // stub cache.
1497 MaybeObject* maybe_code = NULL; 1512 MaybeObject* maybe_code = NULL;
1498 Object* code = NULL; 1513 Object* code = NULL;
1499 switch (type) { 1514 switch (type) {
1500 case FIELD: { 1515 case FIELD: {
1501 maybe_code = StubCache::ComputeStoreField(*name, *receiver, 1516 maybe_code = StubCache::ComputeStoreField(
1502 lookup->GetFieldIndex()); 1517 *name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state);
1503 break; 1518 break;
1504 } 1519 }
1505 case MAP_TRANSITION: { 1520 case MAP_TRANSITION: {
1506 if (lookup->GetAttributes() != NONE) return; 1521 if (lookup->GetAttributes() != NONE) return;
1507 HandleScope scope; 1522 HandleScope scope;
1508 ASSERT(type == MAP_TRANSITION); 1523 ASSERT(type == MAP_TRANSITION);
1509 Handle<Map> transition(lookup->GetTransitionMap()); 1524 Handle<Map> transition(lookup->GetTransitionMap());
1510 int index = transition->PropertyIndexFor(*name); 1525 int index = transition->PropertyIndexFor(*name);
1511 maybe_code = StubCache::ComputeStoreField(*name, *receiver, 1526 maybe_code = StubCache::ComputeStoreField(
1512 index, *transition); 1527 *name, *receiver, index, *transition, extra_ic_state);
1513 break; 1528 break;
1514 } 1529 }
1515 case NORMAL: { 1530 case NORMAL: {
1516 if (receiver->IsGlobalObject()) { 1531 if (receiver->IsGlobalObject()) {
1517 // The stub generated for the global object picks the value directly 1532 // The stub generated for the global object picks the value directly
1518 // from the property cell. So the property must be directly on the 1533 // from the property cell. So the property must be directly on the
1519 // global object. 1534 // global object.
1520 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1535 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1521 JSGlobalPropertyCell* cell = 1536 JSGlobalPropertyCell* cell =
1522 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 1537 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
1523 maybe_code = StubCache::ComputeStoreGlobal(*name, *global, cell); 1538 maybe_code = StubCache::ComputeStoreGlobal(
1539 *name, *global, cell, extra_ic_state);
1524 } else { 1540 } else {
1525 if (lookup->holder() != *receiver) return; 1541 if (lookup->holder() != *receiver) return;
1526 maybe_code = StubCache::ComputeStoreNormal(); 1542 maybe_code = StubCache::ComputeStoreNormal(extra_ic_state);
1527 } 1543 }
1528 break; 1544 break;
1529 } 1545 }
1530 case CALLBACKS: { 1546 case CALLBACKS: {
1531 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1547 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
1532 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1548 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1533 if (v8::ToCData<Address>(callback->setter()) == 0) return; 1549 if (v8::ToCData<Address>(callback->setter()) == 0) return;
1534 maybe_code = StubCache::ComputeStoreCallback(*name, *receiver, callback); 1550 maybe_code = StubCache::ComputeStoreCallback(
1551 *name, *receiver, callback, extra_ic_state);
1535 break; 1552 break;
1536 } 1553 }
1537 case INTERCEPTOR: { 1554 case INTERCEPTOR: {
1538 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); 1555 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1539 maybe_code = StubCache::ComputeStoreInterceptor(*name, *receiver); 1556 maybe_code = StubCache::ComputeStoreInterceptor(
1557 *name, *receiver, extra_ic_state);
1540 break; 1558 break;
1541 } 1559 }
1542 default: 1560 default:
1543 return; 1561 return;
1544 } 1562 }
1545 1563
1546 // If we're unable to compute the stub (not enough memory left), we 1564 // If we're unable to compute the stub (not enough memory left), we
1547 // simply avoid updating the caches. 1565 // simply avoid updating the caches.
1548 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; 1566 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1549 1567
1550 // Patch the call site depending on the state of the cache. 1568 // Patch the call site depending on the state of the cache.
1551 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { 1569 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1552 set_target(Code::cast(code)); 1570 set_target(Code::cast(code));
1553 } else if (state == MONOMORPHIC) { 1571 } else if (state == MONOMORPHIC) {
1554 // Only move to megamorphic if the target changes. 1572 // Only move to megamorphic if the target changes.
1555 if (target() != Code::cast(code)) set_target(megamorphic_stub()); 1573 if (target() != Code::cast(code)) {
1574 set_target(extra_ic_state == kStoreICStrict
1575 ? megamorphic_stub_strict()
1576 : megamorphic_stub());
1577 }
1556 } else if (state == MEGAMORPHIC) { 1578 } else if (state == MEGAMORPHIC) {
1557 // Update the stub cache. 1579 // Update the stub cache.
1558 StubCache::Set(*name, receiver->map(), Code::cast(code)); 1580 StubCache::Set(*name, receiver->map(), Code::cast(code));
1559 } 1581 }
1560 1582
1561 #ifdef DEBUG 1583 #ifdef DEBUG
1562 TraceIC("StoreIC", name, state, target()); 1584 TraceIC("StoreIC", name, state, target());
1563 #endif 1585 #endif
1564 } 1586 }
1565 1587
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1788 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); 1810 return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
1789 } 1811 }
1790 1812
1791 1813
1792 // Used from ic-<arch>.cc. 1814 // Used from ic-<arch>.cc.
1793 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { 1815 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
1794 NoHandleAllocation na; 1816 NoHandleAllocation na;
1795 ASSERT(args.length() == 3); 1817 ASSERT(args.length() == 3);
1796 StoreIC ic; 1818 StoreIC ic;
1797 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1819 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1798 return ic.Store(state, args.at<Object>(0), args.at<String>(1), 1820 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1799 args.at<Object>(2)); 1821 return ic.Store(state, extra_ic_state, args.at<Object>(0),
1822 args.at<String>(1), args.at<Object>(2));
1800 } 1823 }
1801 1824
1802 1825
1803 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) { 1826 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) {
1804 NoHandleAllocation nha; 1827 NoHandleAllocation nha;
1805 1828
1806 ASSERT(args.length() == 2); 1829 ASSERT(args.length() == 2);
1807 JSObject* receiver = JSObject::cast(args[0]); 1830 JSObject* receiver = JSObject::cast(args[0]);
1808 Object* len = args[1]; 1831 Object* len = args[1];
1809 1832
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
2257 #undef ADDR 2280 #undef ADDR
2258 }; 2281 };
2259 2282
2260 2283
2261 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2284 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2262 return IC_utilities[id]; 2285 return IC_utilities[id];
2263 } 2286 }
2264 2287
2265 2288
2266 } } // namespace v8::internal 2289 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | src/stub-cache.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698