| 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 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 // Declaring a const context slot is a conflicting declaration if | 1427 // Declaring a const context slot is a conflicting declaration if |
| 1428 // there is a callback with that name in a prototype. It is | 1428 // there is a callback with that name in a prototype. It is |
| 1429 // allowed to introduce const variables in | 1429 // allowed to introduce const variables in |
| 1430 // JSContextExtensionObjects. They are treated specially in | 1430 // JSContextExtensionObjects. They are treated specially in |
| 1431 // SetProperty and no setters are invoked for those since they are | 1431 // SetProperty and no setters are invoked for those since they are |
| 1432 // not real JSObjects. | 1432 // not real JSObjects. |
| 1433 if (initial_value->IsTheHole() && | 1433 if (initial_value->IsTheHole() && |
| 1434 !object->IsJSContextExtensionObject()) { | 1434 !object->IsJSContextExtensionObject()) { |
| 1435 LookupResult lookup(isolate); | 1435 LookupResult lookup(isolate); |
| 1436 object->Lookup(*name, &lookup); | 1436 object->Lookup(*name, &lookup); |
| 1437 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { | 1437 if (lookup.IsFound() && (lookup.type() == CALLBACKS)) { |
| 1438 return ThrowRedeclarationError(isolate, "const", name); | 1438 return ThrowRedeclarationError(isolate, "const", name); |
| 1439 } | 1439 } |
| 1440 } | 1440 } |
| 1441 RETURN_IF_EMPTY_HANDLE( | 1441 RETURN_IF_EMPTY_HANDLE( |
| 1442 isolate, | 1442 isolate, |
| 1443 JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode)); | 1443 JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode)); |
| 1444 } | 1444 } |
| 1445 | 1445 |
| 1446 return isolate->heap()->undefined_value(); | 1446 return isolate->heap()->undefined_value(); |
| 1447 } | 1447 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1475 // locally if there is an explicit initialization value that we have | 1475 // locally if there is an explicit initialization value that we have |
| 1476 // to assign to the property. | 1476 // to assign to the property. |
| 1477 // Note that objects can have hidden prototypes, so we need to traverse | 1477 // Note that objects can have hidden prototypes, so we need to traverse |
| 1478 // the whole chain of hidden prototypes to do a 'local' lookup. | 1478 // the whole chain of hidden prototypes to do a 'local' lookup. |
| 1479 Object* object = global; | 1479 Object* object = global; |
| 1480 LookupResult lookup(isolate); | 1480 LookupResult lookup(isolate); |
| 1481 while (object->IsJSObject() && | 1481 while (object->IsJSObject() && |
| 1482 JSObject::cast(object)->map()->is_hidden_prototype()) { | 1482 JSObject::cast(object)->map()->is_hidden_prototype()) { |
| 1483 JSObject* raw_holder = JSObject::cast(object); | 1483 JSObject* raw_holder = JSObject::cast(object); |
| 1484 raw_holder->LocalLookup(*name, &lookup); | 1484 raw_holder->LocalLookup(*name, &lookup); |
| 1485 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { | 1485 if (lookup.IsFound() && lookup.type() == INTERCEPTOR) { |
| 1486 HandleScope handle_scope(isolate); | 1486 HandleScope handle_scope(isolate); |
| 1487 Handle<JSObject> holder(raw_holder); | 1487 Handle<JSObject> holder(raw_holder); |
| 1488 PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); | 1488 PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); |
| 1489 // Update the raw pointer in case it's changed due to GC. | 1489 // Update the raw pointer in case it's changed due to GC. |
| 1490 raw_holder = *holder; | 1490 raw_holder = *holder; |
| 1491 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { | 1491 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { |
| 1492 // Found an interceptor that's not read only. | 1492 // Found an interceptor that's not read only. |
| 1493 if (assign) { | 1493 if (assign) { |
| 1494 return raw_holder->SetProperty( | 1494 return raw_holder->SetProperty( |
| 1495 &lookup, *name, args[2], attributes, strict_mode_flag); | 1495 &lookup, *name, args[2], attributes, strict_mode_flag); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1641 // | 1641 // |
| 1642 // In that case, the initialization behaves like a normal assignment. | 1642 // In that case, the initialization behaves like a normal assignment. |
| 1643 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 1643 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 1644 | 1644 |
| 1645 if (*object == context->extension()) { | 1645 if (*object == context->extension()) { |
| 1646 // This is the property that was introduced by the const declaration. | 1646 // This is the property that was introduced by the const declaration. |
| 1647 // Set it if it hasn't been set before. NOTE: We cannot use | 1647 // Set it if it hasn't been set before. NOTE: We cannot use |
| 1648 // GetProperty() to get the current value as it 'unholes' the value. | 1648 // GetProperty() to get the current value as it 'unholes' the value. |
| 1649 LookupResult lookup(isolate); | 1649 LookupResult lookup(isolate); |
| 1650 object->LocalLookupRealNamedProperty(*name, &lookup); | 1650 object->LocalLookupRealNamedProperty(*name, &lookup); |
| 1651 ASSERT(lookup.IsProperty()); // the property was declared | 1651 ASSERT(lookup.IsFound()); // the property was declared |
| 1652 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only | 1652 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only |
| 1653 | 1653 |
| 1654 PropertyType type = lookup.type(); | 1654 PropertyType type = lookup.type(); |
| 1655 if (type == FIELD) { | 1655 if (type == FIELD) { |
| 1656 FixedArray* properties = object->properties(); | 1656 FixedArray* properties = object->properties(); |
| 1657 int index = lookup.GetFieldIndex(); | 1657 int index = lookup.GetFieldIndex(); |
| 1658 if (properties->get(index)->IsTheHole()) { | 1658 if (properties->get(index)->IsTheHole()) { |
| 1659 properties->set(index, *value); | 1659 properties->set(index, *value); |
| 1660 } | 1660 } |
| 1661 } else if (type == NORMAL) { | 1661 } else if (type == NORMAL) { |
| (...skipping 2587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4249 if (offset != -1) { | 4249 if (offset != -1) { |
| 4250 Object* value = receiver->FastPropertyAt(offset); | 4250 Object* value = receiver->FastPropertyAt(offset); |
| 4251 return value->IsTheHole() | 4251 return value->IsTheHole() |
| 4252 ? isolate->heap()->undefined_value() | 4252 ? isolate->heap()->undefined_value() |
| 4253 : value; | 4253 : value; |
| 4254 } | 4254 } |
| 4255 // Lookup cache miss. Perform lookup and update the cache if | 4255 // Lookup cache miss. Perform lookup and update the cache if |
| 4256 // appropriate. | 4256 // appropriate. |
| 4257 LookupResult result(isolate); | 4257 LookupResult result(isolate); |
| 4258 receiver->LocalLookup(key, &result); | 4258 receiver->LocalLookup(key, &result); |
| 4259 if (result.IsProperty() && result.type() == FIELD) { | 4259 if (result.IsFound() && result.type() == FIELD) { |
| 4260 int offset = result.GetFieldIndex(); | 4260 int offset = result.GetFieldIndex(); |
| 4261 keyed_lookup_cache->Update(receiver_map, key, offset); | 4261 keyed_lookup_cache->Update(receiver_map, key, offset); |
| 4262 return receiver->FastPropertyAt(offset); | 4262 return receiver->FastPropertyAt(offset); |
| 4263 } | 4263 } |
| 4264 } else { | 4264 } else { |
| 4265 // Attempt dictionary lookup. | 4265 // Attempt dictionary lookup. |
| 4266 StringDictionary* dictionary = receiver->property_dictionary(); | 4266 StringDictionary* dictionary = receiver->property_dictionary(); |
| 4267 int entry = dictionary->FindEntry(key); | 4267 int entry = dictionary->FindEntry(key); |
| 4268 if ((entry != StringDictionary::kNotFound) && | 4268 if ((entry != StringDictionary::kNotFound) && |
| 4269 (dictionary->DetailsAt(entry).type() == NORMAL)) { | 4269 (dictionary->DetailsAt(entry).type() == NORMAL)) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4397 js_object->set_elements(*extended_dictionary); | 4397 js_object->set_elements(*extended_dictionary); |
| 4398 } | 4398 } |
| 4399 } | 4399 } |
| 4400 return *obj_value; | 4400 return *obj_value; |
| 4401 } | 4401 } |
| 4402 | 4402 |
| 4403 LookupResult result(isolate); | 4403 LookupResult result(isolate); |
| 4404 js_object->LocalLookupRealNamedProperty(*name, &result); | 4404 js_object->LocalLookupRealNamedProperty(*name, &result); |
| 4405 | 4405 |
| 4406 // Special case for callback properties. | 4406 // Special case for callback properties. |
| 4407 if (result.IsProperty() && result.type() == CALLBACKS) { | 4407 if (result.IsFound() && result.type() == CALLBACKS) { |
| 4408 Object* callback = result.GetCallbackObject(); | 4408 Object* callback = result.GetCallbackObject(); |
| 4409 // To be compatible with Safari we do not change the value on API objects | 4409 // To be compatible with Safari we do not change the value on API objects |
| 4410 // in Object.defineProperty(). Firefox disagrees here, and actually changes | 4410 // in Object.defineProperty(). Firefox disagrees here, and actually changes |
| 4411 // the value. | 4411 // the value. |
| 4412 if (callback->IsAccessorInfo()) { | 4412 if (callback->IsAccessorInfo()) { |
| 4413 return isolate->heap()->undefined_value(); | 4413 return isolate->heap()->undefined_value(); |
| 4414 } | 4414 } |
| 4415 // Avoid redefining foreign callback as data property, just use the stored | 4415 // Avoid redefining foreign callback as data property, just use the stored |
| 4416 // setter to update the value instead. | 4416 // setter to update the value instead. |
| 4417 // TODO(mstarzinger): So far this only works if property attributes don't | 4417 // TODO(mstarzinger): So far this only works if property attributes don't |
| (...skipping 9217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13635 } else { | 13635 } else { |
| 13636 // Handle last resort GC and make sure to allow future allocations | 13636 // Handle last resort GC and make sure to allow future allocations |
| 13637 // to grow the heap without causing GCs (if possible). | 13637 // to grow the heap without causing GCs (if possible). |
| 13638 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13638 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13639 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 13639 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 13640 } | 13640 } |
| 13641 } | 13641 } |
| 13642 | 13642 |
| 13643 | 13643 |
| 13644 } } // namespace v8::internal | 13644 } } // namespace v8::internal |
| OLD | NEW |