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

Side by Side Diff: src/ic.cc

Issue 6594037: Strict Mode assignment to read only property. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: CR Feedback. Created 9 years, 9 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/ic-inl.h » ('j') | no next file with comments »
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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
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, 345 SetTargetAtAddress(address,
346 target->extra_ic_state() == kStoreICStrict 346 (target->extra_ic_state() == kStrictMode)
347 ? initialize_stub_strict() 347 ? initialize_stub_strict()
348 : initialize_stub()); 348 : initialize_stub());
349 } 349 }
350 350
351 351
352 void KeyedStoreIC::ClearInlinedVersion(Address address) { 352 void KeyedStoreIC::ClearInlinedVersion(Address address) {
353 // 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
354 // 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
355 // flows to the IC instead of the inlined version. 355 // flows to the IC instead of the inlined version.
356 PatchInlinedStore(address, Heap::null_value()); 356 PatchInlinedStore(address, Heap::null_value());
357 } 357 }
358 358
359 359
360 void KeyedStoreIC::RestoreInlinedVersion(Address address) { 360 void KeyedStoreIC::RestoreInlinedVersion(Address address) {
361 // Restore the fast-case elements map check so that the inlined 361 // Restore the fast-case elements map check so that the inlined
362 // version can be used again. 362 // version can be used again.
363 PatchInlinedStore(address, Heap::fixed_array_map()); 363 PatchInlinedStore(address, Heap::fixed_array_map());
364 } 364 }
365 365
366 366
367 void KeyedStoreIC::Clear(Address address, Code* target) { 367 void KeyedStoreIC::Clear(Address address, Code* target) {
368 if (target->ic_state() == UNINITIALIZED) return; 368 if (target->ic_state() == UNINITIALIZED) return;
369 SetTargetAtAddress(address, initialize_stub()); 369 SetTargetAtAddress(address,
370 (target->extra_ic_state() == kStrictMode)
371 ? initialize_stub_strict()
372 : initialize_stub());
370 } 373 }
371 374
372 375
373 static bool HasInterceptorGetter(JSObject* object) { 376 static bool HasInterceptorGetter(JSObject* object) {
374 return !object->GetNamedInterceptor()->getter()->IsUndefined(); 377 return !object->GetNamedInterceptor()->getter()->IsUndefined();
375 } 378 }
376 379
377 380
378 static void LookupForRead(Object* object, 381 static void LookupForRead(Object* object,
379 String* name, 382 String* name,
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after
1220 if (use_ic) { 1223 if (use_ic) {
1221 Code* stub = generic_stub(); 1224 Code* stub = generic_stub();
1222 if (state == UNINITIALIZED) { 1225 if (state == UNINITIALIZED) {
1223 if (object->IsString() && key->IsNumber()) { 1226 if (object->IsString() && key->IsNumber()) {
1224 stub = string_stub(); 1227 stub = string_stub();
1225 } else if (object->IsJSObject()) { 1228 } else if (object->IsJSObject()) {
1226 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1229 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1227 if (receiver->HasExternalArrayElements()) { 1230 if (receiver->HasExternalArrayElements()) {
1228 MaybeObject* probe = 1231 MaybeObject* probe =
1229 StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, 1232 StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver,
1230 false); 1233 false,
1234 kNonStrictMode);
1231 stub = probe->IsFailure() ? 1235 stub = probe->IsFailure() ?
1232 NULL : Code::cast(probe->ToObjectUnchecked()); 1236 NULL : Code::cast(probe->ToObjectUnchecked());
1233 } else if (receiver->HasIndexedInterceptor()) { 1237 } else if (receiver->HasIndexedInterceptor()) {
1234 stub = indexed_interceptor_stub(); 1238 stub = indexed_interceptor_stub();
1235 } else if (receiver->HasPixelElements()) { 1239 } else if (receiver->HasPixelElements()) {
1236 MaybeObject* probe = 1240 MaybeObject* probe =
1237 StubCache::ComputeKeyedLoadPixelArray(*receiver); 1241 StubCache::ComputeKeyedLoadPixelArray(*receiver);
1238 stub = probe->IsFailure() ? 1242 stub = probe->IsFailure() ?
1239 NULL : Code::cast(probe->ToObjectUnchecked()); 1243 NULL : Code::cast(probe->ToObjectUnchecked());
1240 } else if (key->IsSmi() && 1244 } else if (key->IsSmi() &&
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 object->LocalLookupRealNamedProperty(name, lookup); 1380 object->LocalLookupRealNamedProperty(name, lookup);
1377 return StoreICableLookup(lookup); 1381 return StoreICableLookup(lookup);
1378 } 1382 }
1379 } 1383 }
1380 1384
1381 return true; 1385 return true;
1382 } 1386 }
1383 1387
1384 1388
1385 MaybeObject* StoreIC::Store(State state, 1389 MaybeObject* StoreIC::Store(State state,
1386 Code::ExtraICState extra_ic_state, 1390 StrictModeFlag strict_mode,
1387 Handle<Object> object, 1391 Handle<Object> object,
1388 Handle<String> name, 1392 Handle<String> name,
1389 Handle<Object> value) { 1393 Handle<Object> value) {
1390 // If the object is undefined or null it's illegal to try to set any 1394 // If the object is undefined or null it's illegal to try to set any
1391 // properties on it; throw a TypeError in that case. 1395 // properties on it; throw a TypeError in that case.
1392 if (object->IsUndefined() || object->IsNull()) { 1396 if (object->IsUndefined() || object->IsNull()) {
1393 return TypeError("non_object_property_store", object, name); 1397 return TypeError("non_object_property_store", object, name);
1394 } 1398 }
1395 1399
1396 // Ignore stores where the receiver is not a JSObject. 1400 // Ignore stores where the receiver is not a JSObject.
1397 if (!object->IsJSObject()) return *value; 1401 if (!object->IsJSObject()) return *value;
1398 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1402 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1399 1403
1400 // Check if the given name is an array index. 1404 // Check if the given name is an array index.
1401 uint32_t index; 1405 uint32_t index;
1402 if (name->AsArrayIndex(&index)) { 1406 if (name->AsArrayIndex(&index)) {
1403 HandleScope scope; 1407 HandleScope scope;
1404 Handle<Object> result = SetElement(receiver, index, value); 1408 Handle<Object> result = SetElement(receiver, index, value);
1405 if (result.is_null()) return Failure::Exception(); 1409 if (result.is_null()) return Failure::Exception();
1406 return *value; 1410 return *value;
1407 } 1411 }
1408 1412
1409 // Use specialized code for setting the length of arrays. 1413 // Use specialized code for setting the length of arrays.
1410 if (receiver->IsJSArray() 1414 if (receiver->IsJSArray()
1411 && name->Equals(Heap::length_symbol()) 1415 && name->Equals(Heap::length_symbol())
1412 && receiver->AllowsSetElementsLength()) { 1416 && receiver->AllowsSetElementsLength()) {
1413 #ifdef DEBUG 1417 #ifdef DEBUG
1414 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); 1418 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1415 #endif 1419 #endif
1416 Builtins::Name target = (extra_ic_state == kStoreICStrict) 1420 Builtins::Name target = (strict_mode == kStrictMode)
1417 ? Builtins::StoreIC_ArrayLength_Strict 1421 ? Builtins::StoreIC_ArrayLength_Strict
1418 : Builtins::StoreIC_ArrayLength; 1422 : Builtins::StoreIC_ArrayLength;
1419 set_target(Builtins::builtin(target)); 1423 set_target(Builtins::builtin(target));
1420 return receiver->SetProperty(*name, *value, NONE); 1424 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1421 } 1425 }
1422 1426
1423 // Lookup the property locally in the receiver. 1427 // Lookup the property locally in the receiver.
1424 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { 1428 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1425 LookupResult lookup; 1429 LookupResult lookup;
1426 1430
1427 if (LookupForWrite(*receiver, *name, &lookup)) { 1431 if (LookupForWrite(*receiver, *name, &lookup)) {
1428 bool can_be_inlined = 1432 bool can_be_inlined =
1429 state == UNINITIALIZED && 1433 state == UNINITIALIZED &&
1430 lookup.IsProperty() && 1434 lookup.IsProperty() &&
1431 lookup.holder() == *receiver && 1435 lookup.holder() == *receiver &&
1432 lookup.type() == FIELD && 1436 lookup.type() == FIELD &&
1433 !receiver->IsAccessCheckNeeded(); 1437 !receiver->IsAccessCheckNeeded();
1434 1438
1435 if (can_be_inlined) { 1439 if (can_be_inlined) {
1436 Map* map = lookup.holder()->map(); 1440 Map* map = lookup.holder()->map();
1437 // Property's index in the properties array. If negative we have 1441 // Property's index in the properties array. If negative we have
1438 // an inobject property. 1442 // an inobject property.
1439 int index = lookup.GetFieldIndex() - map->inobject_properties(); 1443 int index = lookup.GetFieldIndex() - map->inobject_properties();
1440 if (index < 0) { 1444 if (index < 0) {
1441 // Index is an offset from the end of the object. 1445 // Index is an offset from the end of the object.
1442 int offset = map->instance_size() + (index * kPointerSize); 1446 int offset = map->instance_size() + (index * kPointerSize);
1443 if (PatchInlinedStore(address(), map, offset)) { 1447 if (PatchInlinedStore(address(), map, offset)) {
1444 set_target(megamorphic_stub()); 1448 set_target((strict_mode == kStrictMode)
1449 ? megamorphic_stub_strict()
1450 : megamorphic_stub());
1445 #ifdef DEBUG 1451 #ifdef DEBUG
1446 if (FLAG_trace_ic) { 1452 if (FLAG_trace_ic) {
1447 PrintF("[StoreIC : inline patch %s]\n", *name->ToCString()); 1453 PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
1448 } 1454 }
1449 #endif 1455 #endif
1450 return receiver->SetProperty(*name, *value, NONE); 1456 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1451 #ifdef DEBUG 1457 #ifdef DEBUG
1452 1458
1453 } else { 1459 } else {
1454 if (FLAG_trace_ic) { 1460 if (FLAG_trace_ic) {
1455 PrintF("[StoreIC : no inline patch %s (patching failed)]\n", 1461 PrintF("[StoreIC : no inline patch %s (patching failed)]\n",
1456 *name->ToCString()); 1462 *name->ToCString());
1457 } 1463 }
1458 } 1464 }
1459 } else { 1465 } else {
1460 if (FLAG_trace_ic) { 1466 if (FLAG_trace_ic) {
1461 PrintF("[StoreIC : no inline patch %s (not inobject)]\n", 1467 PrintF("[StoreIC : no inline patch %s (not inobject)]\n",
1462 *name->ToCString()); 1468 *name->ToCString());
1463 } 1469 }
1464 } 1470 }
1465 } else { 1471 } else {
1466 if (state == PREMONOMORPHIC) { 1472 if (state == PREMONOMORPHIC) {
1467 if (FLAG_trace_ic) { 1473 if (FLAG_trace_ic) {
1468 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n", 1474 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n",
1469 *name->ToCString()); 1475 *name->ToCString());
1470 #endif 1476 #endif
1471 } 1477 }
1472 } 1478 }
1473 } 1479 }
1474 1480
1475 // If no inlined store ic was patched, generate a stub for this 1481 // If no inlined store ic was patched, generate a stub for this
1476 // store. 1482 // store.
1477 UpdateCaches(&lookup, state, extra_ic_state, receiver, name, value); 1483 UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1478 } else { 1484 } else {
1479 // Strict mode doesn't allow setting non-existent global property. 1485 // Strict mode doesn't allow setting non-existent global property
1480 if (extra_ic_state == kStoreICStrict && IsContextual(object)) { 1486 // or an assignment to a read only property.
1481 return ReferenceError("not_defined", name); 1487 if (strict_mode == kStrictMode) {
1488 if (lookup.IsFound() && lookup.IsReadOnly()) {
1489 return TypeError("strict_read_only_property", object, name);
1490 } else if (IsContextual(object)) {
1491 return ReferenceError("not_defined", name);
1492 }
1482 } 1493 }
1483 } 1494 }
1484 } 1495 }
1485 1496
1486 if (receiver->IsJSGlobalProxy()) { 1497 if (receiver->IsJSGlobalProxy()) {
1487 // Generate a generic stub that goes to the runtime when we see a global 1498 // Generate a generic stub that goes to the runtime when we see a global
1488 // proxy as receiver. 1499 // proxy as receiver.
1489 Code* stub = (extra_ic_state == kStoreICStrict) 1500 Code* stub = (strict_mode == kStrictMode)
1490 ? global_proxy_stub_strict() 1501 ? global_proxy_stub_strict()
1491 : global_proxy_stub(); 1502 : global_proxy_stub();
1492 if (target() != stub) { 1503 if (target() != stub) {
1493 set_target(stub); 1504 set_target(stub);
1494 #ifdef DEBUG 1505 #ifdef DEBUG
1495 TraceIC("StoreIC", name, state, target()); 1506 TraceIC("StoreIC", name, state, target());
1496 #endif 1507 #endif
1497 } 1508 }
1498 } 1509 }
1499 1510
1500 // Set the property. 1511 // Set the property.
1501 return receiver->SetProperty(*name, *value, NONE); 1512 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1502 } 1513 }
1503 1514
1504 1515
1505 void StoreIC::UpdateCaches(LookupResult* lookup, 1516 void StoreIC::UpdateCaches(LookupResult* lookup,
1506 State state, 1517 State state,
1507 Code::ExtraICState extra_ic_state, 1518 StrictModeFlag strict_mode,
1508 Handle<JSObject> receiver, 1519 Handle<JSObject> receiver,
1509 Handle<String> name, 1520 Handle<String> name,
1510 Handle<Object> value) { 1521 Handle<Object> value) {
1511 // Skip JSGlobalProxy. 1522 // Skip JSGlobalProxy.
1512 ASSERT(!receiver->IsJSGlobalProxy()); 1523 ASSERT(!receiver->IsJSGlobalProxy());
1513 1524
1514 ASSERT(StoreICableLookup(lookup)); 1525 ASSERT(StoreICableLookup(lookup));
1515 1526
1516 // If the property has a non-field type allowing map transitions 1527 // If the property has a non-field type allowing map transitions
1517 // where there is extra room in the object, we leave the IC in its 1528 // where there is extra room in the object, we leave the IC in its
1518 // current state. 1529 // current state.
1519 PropertyType type = lookup->type(); 1530 PropertyType type = lookup->type();
1520 1531
1521 // Compute the code stub for this store; used for rewriting to 1532 // Compute the code stub for this store; used for rewriting to
1522 // monomorphic state and making sure that the code stub is in the 1533 // monomorphic state and making sure that the code stub is in the
1523 // stub cache. 1534 // stub cache.
1524 MaybeObject* maybe_code = NULL; 1535 MaybeObject* maybe_code = NULL;
1525 Object* code = NULL; 1536 Object* code = NULL;
1526 switch (type) { 1537 switch (type) {
1527 case FIELD: { 1538 case FIELD: {
1528 maybe_code = StubCache::ComputeStoreField( 1539 maybe_code = StubCache::ComputeStoreField(
1529 *name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state); 1540 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
1530 break; 1541 break;
1531 } 1542 }
1532 case MAP_TRANSITION: { 1543 case MAP_TRANSITION: {
1533 if (lookup->GetAttributes() != NONE) return; 1544 if (lookup->GetAttributes() != NONE) return;
1534 HandleScope scope; 1545 HandleScope scope;
1535 ASSERT(type == MAP_TRANSITION); 1546 ASSERT(type == MAP_TRANSITION);
1536 Handle<Map> transition(lookup->GetTransitionMap()); 1547 Handle<Map> transition(lookup->GetTransitionMap());
1537 int index = transition->PropertyIndexFor(*name); 1548 int index = transition->PropertyIndexFor(*name);
1538 maybe_code = StubCache::ComputeStoreField( 1549 maybe_code = StubCache::ComputeStoreField(
1539 *name, *receiver, index, *transition, extra_ic_state); 1550 *name, *receiver, index, *transition, strict_mode);
1540 break; 1551 break;
1541 } 1552 }
1542 case NORMAL: { 1553 case NORMAL: {
1543 if (receiver->IsGlobalObject()) { 1554 if (receiver->IsGlobalObject()) {
1544 // The stub generated for the global object picks the value directly 1555 // The stub generated for the global object picks the value directly
1545 // from the property cell. So the property must be directly on the 1556 // from the property cell. So the property must be directly on the
1546 // global object. 1557 // global object.
1547 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1558 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1548 JSGlobalPropertyCell* cell = 1559 JSGlobalPropertyCell* cell =
1549 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 1560 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
1550 maybe_code = StubCache::ComputeStoreGlobal( 1561 maybe_code = StubCache::ComputeStoreGlobal(
1551 *name, *global, cell, extra_ic_state); 1562 *name, *global, cell, strict_mode);
1552 } else { 1563 } else {
1553 if (lookup->holder() != *receiver) return; 1564 if (lookup->holder() != *receiver) return;
1554 maybe_code = StubCache::ComputeStoreNormal(extra_ic_state); 1565 maybe_code = StubCache::ComputeStoreNormal(strict_mode);
1555 } 1566 }
1556 break; 1567 break;
1557 } 1568 }
1558 case CALLBACKS: { 1569 case CALLBACKS: {
1559 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1570 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
1560 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1571 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1561 if (v8::ToCData<Address>(callback->setter()) == 0) return; 1572 if (v8::ToCData<Address>(callback->setter()) == 0) return;
1562 maybe_code = StubCache::ComputeStoreCallback( 1573 maybe_code = StubCache::ComputeStoreCallback(
1563 *name, *receiver, callback, extra_ic_state); 1574 *name, *receiver, callback, strict_mode);
1564 break; 1575 break;
1565 } 1576 }
1566 case INTERCEPTOR: { 1577 case INTERCEPTOR: {
1567 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); 1578 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1568 maybe_code = StubCache::ComputeStoreInterceptor( 1579 maybe_code = StubCache::ComputeStoreInterceptor(
1569 *name, *receiver, extra_ic_state); 1580 *name, *receiver, strict_mode);
1570 break; 1581 break;
1571 } 1582 }
1572 default: 1583 default:
1573 return; 1584 return;
1574 } 1585 }
1575 1586
1576 // If we're unable to compute the stub (not enough memory left), we 1587 // If we're unable to compute the stub (not enough memory left), we
1577 // simply avoid updating the caches. 1588 // simply avoid updating the caches.
1578 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; 1589 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1579 1590
1580 // Patch the call site depending on the state of the cache. 1591 // Patch the call site depending on the state of the cache.
1581 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { 1592 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1582 set_target(Code::cast(code)); 1593 set_target(Code::cast(code));
1583 } else if (state == MONOMORPHIC) { 1594 } else if (state == MONOMORPHIC) {
1584 // Only move to megamorphic if the target changes. 1595 // Only move to megamorphic if the target changes.
1585 if (target() != Code::cast(code)) { 1596 if (target() != Code::cast(code)) {
1586 set_target(extra_ic_state == kStoreICStrict 1597 set_target((strict_mode == kStrictMode)
1587 ? megamorphic_stub_strict() 1598 ? megamorphic_stub_strict()
1588 : megamorphic_stub()); 1599 : megamorphic_stub());
1589 } 1600 }
1590 } else if (state == MEGAMORPHIC) { 1601 } else if (state == MEGAMORPHIC) {
1591 // Update the stub cache. 1602 // Update the stub cache.
1592 StubCache::Set(*name, receiver->map(), Code::cast(code)); 1603 StubCache::Set(*name, receiver->map(), Code::cast(code));
1593 } 1604 }
1594 1605
1595 #ifdef DEBUG 1606 #ifdef DEBUG
1596 TraceIC("StoreIC", name, state, target()); 1607 TraceIC("StoreIC", name, state, target());
1597 #endif 1608 #endif
1598 } 1609 }
1599 1610
1600 1611
1601 MaybeObject* KeyedStoreIC::Store(State state, 1612 MaybeObject* KeyedStoreIC::Store(State state,
1613 StrictModeFlag strict_mode,
1602 Handle<Object> object, 1614 Handle<Object> object,
1603 Handle<Object> key, 1615 Handle<Object> key,
1604 Handle<Object> value) { 1616 Handle<Object> value) {
1605 if (key->IsSymbol()) { 1617 if (key->IsSymbol()) {
1606 Handle<String> name = Handle<String>::cast(key); 1618 Handle<String> name = Handle<String>::cast(key);
1607 1619
1608 // If the object is undefined or null it's illegal to try to set any 1620 // If the object is undefined or null it's illegal to try to set any
1609 // properties on it; throw a TypeError in that case. 1621 // properties on it; throw a TypeError in that case.
1610 if (object->IsUndefined() || object->IsNull()) { 1622 if (object->IsUndefined() || object->IsNull()) {
1611 return TypeError("non_object_property_store", object, name); 1623 return TypeError("non_object_property_store", object, name);
(...skipping 11 matching lines...) Expand all
1623 if (result.is_null()) return Failure::Exception(); 1635 if (result.is_null()) return Failure::Exception();
1624 return *value; 1636 return *value;
1625 } 1637 }
1626 1638
1627 // Lookup the property locally in the receiver. 1639 // Lookup the property locally in the receiver.
1628 LookupResult lookup; 1640 LookupResult lookup;
1629 receiver->LocalLookup(*name, &lookup); 1641 receiver->LocalLookup(*name, &lookup);
1630 1642
1631 // Update inline cache and stub cache. 1643 // Update inline cache and stub cache.
1632 if (FLAG_use_ic) { 1644 if (FLAG_use_ic) {
1633 UpdateCaches(&lookup, state, receiver, name, value); 1645 UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1634 } 1646 }
1635 1647
1636 // Set the property. 1648 // Set the property.
1637 return receiver->SetProperty(*name, *value, NONE); 1649 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1638 } 1650 }
1639 1651
1640 // Do not use ICs for objects that require access checks (including 1652 // Do not use ICs for objects that require access checks (including
1641 // the global object). 1653 // the global object).
1642 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1654 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1643 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1655 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1644 1656
1645 if (use_ic) { 1657 if (use_ic) {
1646 Code* stub = generic_stub(); 1658 Code* stub =
1659 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub();
1647 if (state == UNINITIALIZED) { 1660 if (state == UNINITIALIZED) {
1648 if (object->IsJSObject()) { 1661 if (object->IsJSObject()) {
1649 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1662 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1650 if (receiver->HasExternalArrayElements()) { 1663 if (receiver->HasExternalArrayElements()) {
1651 MaybeObject* probe = 1664 MaybeObject* probe =
1652 StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, true); 1665 StubCache::ComputeKeyedLoadOrStoreExternalArray(
1666 *receiver, true, strict_mode);
1653 stub = probe->IsFailure() ? 1667 stub = probe->IsFailure() ?
1654 NULL : Code::cast(probe->ToObjectUnchecked()); 1668 NULL : Code::cast(probe->ToObjectUnchecked());
1655 } else if (receiver->HasPixelElements()) { 1669 } else if (receiver->HasPixelElements()) {
1656 MaybeObject* probe = 1670 MaybeObject* probe =
1657 StubCache::ComputeKeyedStorePixelArray(*receiver); 1671 StubCache::ComputeKeyedStorePixelArray(*receiver, strict_mode);
1658 stub = probe->IsFailure() ? 1672 stub = probe->IsFailure() ?
1659 NULL : Code::cast(probe->ToObjectUnchecked()); 1673 NULL : Code::cast(probe->ToObjectUnchecked());
1660 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { 1674 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
1661 MaybeObject* probe = 1675 MaybeObject* probe =
1662 StubCache::ComputeKeyedStoreSpecialized(*receiver); 1676 StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode);
1663 stub = probe->IsFailure() ? 1677 stub = probe->IsFailure() ?
1664 NULL : Code::cast(probe->ToObjectUnchecked()); 1678 NULL : Code::cast(probe->ToObjectUnchecked());
1665 } 1679 }
1666 } 1680 }
1667 } 1681 }
1668 if (stub != NULL) set_target(stub); 1682 if (stub != NULL) set_target(stub);
1669 } 1683 }
1670 1684
1671 // Set the property. 1685 // Set the property.
1672 return Runtime::SetObjectProperty(object, key, value, NONE); 1686 return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode);
1673 } 1687 }
1674 1688
1675 1689
1676 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1690 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1677 State state, 1691 State state,
1692 StrictModeFlag strict_mode,
1678 Handle<JSObject> receiver, 1693 Handle<JSObject> receiver,
1679 Handle<String> name, 1694 Handle<String> name,
1680 Handle<Object> value) { 1695 Handle<Object> value) {
1681 // Skip JSGlobalProxy. 1696 // Skip JSGlobalProxy.
1682 if (receiver->IsJSGlobalProxy()) return; 1697 if (receiver->IsJSGlobalProxy()) return;
1683 1698
1684 // Bail out if we didn't find a result. 1699 // Bail out if we didn't find a result.
1685 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return; 1700 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return;
1686 1701
1687 // If the property is read-only, we leave the IC in its current 1702 // If the property is read-only, we leave the IC in its current
1688 // state. 1703 // state.
1689 if (lookup->IsReadOnly()) return; 1704 if (lookup->IsReadOnly()) return;
1690 1705
1691 // If the property has a non-field type allowing map transitions 1706 // If the property has a non-field type allowing map transitions
1692 // where there is extra room in the object, we leave the IC in its 1707 // where there is extra room in the object, we leave the IC in its
1693 // current state. 1708 // current state.
1694 PropertyType type = lookup->type(); 1709 PropertyType type = lookup->type();
1695 1710
1696 // Compute the code stub for this store; used for rewriting to 1711 // Compute the code stub for this store; used for rewriting to
1697 // monomorphic state and making sure that the code stub is in the 1712 // monomorphic state and making sure that the code stub is in the
1698 // stub cache. 1713 // stub cache.
1699 MaybeObject* maybe_code = NULL; 1714 MaybeObject* maybe_code = NULL;
1700 Object* code = NULL; 1715 Object* code = NULL;
1701 1716
1702 switch (type) { 1717 switch (type) {
1703 case FIELD: { 1718 case FIELD: {
1704 maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver, 1719 maybe_code = StubCache::ComputeKeyedStoreField(
1705 lookup->GetFieldIndex()); 1720 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
1706 break; 1721 break;
1707 } 1722 }
1708 case MAP_TRANSITION: { 1723 case MAP_TRANSITION: {
1709 if (lookup->GetAttributes() == NONE) { 1724 if (lookup->GetAttributes() == NONE) {
1710 HandleScope scope; 1725 HandleScope scope;
1711 ASSERT(type == MAP_TRANSITION); 1726 ASSERT(type == MAP_TRANSITION);
1712 Handle<Map> transition(lookup->GetTransitionMap()); 1727 Handle<Map> transition(lookup->GetTransitionMap());
1713 int index = transition->PropertyIndexFor(*name); 1728 int index = transition->PropertyIndexFor(*name);
1714 maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver, 1729 maybe_code = StubCache::ComputeKeyedStoreField(
1715 index, *transition); 1730 *name, *receiver, index, *transition, strict_mode);
1716 break; 1731 break;
1717 } 1732 }
1718 // fall through. 1733 // fall through.
1719 } 1734 }
1720 default: { 1735 default: {
1721 // Always rewrite to the generic case so that we do not 1736 // Always rewrite to the generic case so that we do not
1722 // repeatedly try to rewrite. 1737 // repeatedly try to rewrite.
1723 maybe_code = generic_stub(); 1738 maybe_code = (strict_mode == kStrictMode)
1739 ? generic_stub_strict()
1740 : generic_stub();
1724 break; 1741 break;
1725 } 1742 }
1726 } 1743 }
1727 1744
1728 // If we're unable to compute the stub (not enough memory left), we 1745 // If we're unable to compute the stub (not enough memory left), we
1729 // simply avoid updating the caches. 1746 // simply avoid updating the caches.
1730 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; 1747 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1731 1748
1732 // Patch the call site depending on the state of the cache. Make 1749 // Patch the call site depending on the state of the cache. Make
1733 // sure to always rewrite from monomorphic to megamorphic. 1750 // sure to always rewrite from monomorphic to megamorphic.
1734 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); 1751 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1735 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { 1752 if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1736 set_target(Code::cast(code)); 1753 set_target(Code::cast(code));
1737 } else if (state == MONOMORPHIC) { 1754 } else if (state == MONOMORPHIC) {
1738 set_target(megamorphic_stub()); 1755 set_target((strict_mode == kStrictMode)
1756 ? megamorphic_stub_strict()
1757 : megamorphic_stub());
1739 } 1758 }
1740 1759
1741 #ifdef DEBUG 1760 #ifdef DEBUG
1742 TraceIC("KeyedStoreIC", name, state, target()); 1761 TraceIC("KeyedStoreIC", name, state, target());
1743 #endif 1762 #endif
1744 } 1763 }
1745 1764
1746 1765
1747 // ---------------------------------------------------------------------------- 1766 // ----------------------------------------------------------------------------
1748 // Static IC stub generators. 1767 // Static IC stub generators.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 } 1848 }
1830 1849
1831 1850
1832 // Used from ic-<arch>.cc. 1851 // Used from ic-<arch>.cc.
1833 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { 1852 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
1834 NoHandleAllocation na; 1853 NoHandleAllocation na;
1835 ASSERT(args.length() == 3); 1854 ASSERT(args.length() == 3);
1836 StoreIC ic; 1855 StoreIC ic;
1837 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1856 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1838 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 1857 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1839 return ic.Store(state, extra_ic_state, args.at<Object>(0), 1858 return ic.Store(state,
1840 args.at<String>(1), args.at<Object>(2)); 1859 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1860 args.at<Object>(0),
1861 args.at<String>(1),
1862 args.at<Object>(2));
1841 } 1863 }
1842 1864
1843 1865
1844 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) { 1866 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) {
1845 NoHandleAllocation nha; 1867 NoHandleAllocation nha;
1846 1868
1847 ASSERT(args.length() == 2); 1869 ASSERT(args.length() == 2);
1848 JSObject* receiver = JSObject::cast(args[0]); 1870 JSObject* receiver = JSObject::cast(args[0]);
1849 Object* len = args[1]; 1871 Object* len = args[1];
1850 1872
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 return value; 1916 return value;
1895 } 1917 }
1896 1918
1897 1919
1898 // Used from ic-<arch>.cc. 1920 // Used from ic-<arch>.cc.
1899 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) { 1921 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
1900 NoHandleAllocation na; 1922 NoHandleAllocation na;
1901 ASSERT(args.length() == 3); 1923 ASSERT(args.length() == 3);
1902 KeyedStoreIC ic; 1924 KeyedStoreIC ic;
1903 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1925 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1904 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), 1926 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1927 return ic.Store(state,
1928 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1929 args.at<Object>(0),
1930 args.at<Object>(1),
1905 args.at<Object>(2)); 1931 args.at<Object>(2));
1906 } 1932 }
1907 1933
1908 1934
1909 void BinaryOpIC::patch(Code* code) { 1935 void BinaryOpIC::patch(Code* code) {
1910 set_target(code); 1936 set_target(code);
1911 } 1937 }
1912 1938
1913 1939
1914 const char* BinaryOpIC::GetName(TypeInfo type_info) { 1940 const char* BinaryOpIC::GetName(TypeInfo type_info) {
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
2298 #undef ADDR 2324 #undef ADDR
2299 }; 2325 };
2300 2326
2301 2327
2302 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2328 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2303 return IC_utilities[id]; 2329 return IC_utilities[id];
2304 } 2330 }
2305 2331
2306 2332
2307 } } // namespace v8::internal 2333 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698