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

Side by Side Diff: src/objects.cc

Issue 46030: Implementing __defineSetter__ and __defineGetter__ with an array index as arg... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 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
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 } 206 }
207 RETURN_IF_SCHEDULED_EXCEPTION(); 207 RETURN_IF_SCHEDULED_EXCEPTION();
208 if (result.IsEmpty()) return Heap::undefined_value(); 208 if (result.IsEmpty()) return Heap::undefined_value();
209 return *v8::Utils::OpenHandle(*result); 209 return *v8::Utils::OpenHandle(*result);
210 } 210 }
211 211
212 // __defineGetter__ callback 212 // __defineGetter__ callback
213 if (structure->IsFixedArray()) { 213 if (structure->IsFixedArray()) {
214 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); 214 Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
215 if (getter->IsJSFunction()) { 215 if (getter->IsJSFunction()) {
216 HandleScope scope; 216 return Object::GetPropertyWithDefinedGetter(receiver,
217 Handle<JSFunction> fun(JSFunction::cast(getter)); 217 JSFunction::cast(getter));
218 Handle<Object> self(receiver);
219 bool has_pending_exception;
220 Handle<Object> result =
221 Execution::Call(fun, self, 0, NULL, &has_pending_exception);
222 // Check for pending exception and return the result.
223 if (has_pending_exception) return Failure::Exception();
224 return *result;
225 } 218 }
226 // Getter is not a function. 219 // Getter is not a function.
227 return Heap::undefined_value(); 220 return Heap::undefined_value();
228 } 221 }
229 222
230 UNREACHABLE(); 223 UNREACHABLE();
231 return 0; 224 return 0;
232 } 225 }
233 226
234 227
228 Object* Object::GetPropertyWithDefinedGetter(Object* receiver,
229 JSFunction* getter) {
230 HandleScope scope;
231 Handle<JSFunction> fun(JSFunction::cast(getter));
232 Handle<Object> self(receiver);
233 bool has_pending_exception;
234 Handle<Object> result =
235 Execution::Call(fun, self, 0, NULL, &has_pending_exception);
236 // Check for pending exception and return the result.
237 if (has_pending_exception) return Failure::Exception();
238 return *result;
239 }
240
241
235 // Only deal with CALLBACKS and INTERCEPTOR 242 // Only deal with CALLBACKS and INTERCEPTOR
236 Object* JSObject::GetPropertyWithFailedAccessCheck( 243 Object* JSObject::GetPropertyWithFailedAccessCheck(
237 Object* receiver, 244 Object* receiver,
238 LookupResult* result, 245 LookupResult* result,
239 String* name, 246 String* name,
240 PropertyAttributes* attributes) { 247 PropertyAttributes* attributes) {
241 if (result->IsValid()) { 248 if (result->IsValid()) {
242 switch (result->type()) { 249 switch (result->type()) {
243 case CALLBACKS: { 250 case CALLBACKS: {
244 // Only allow API accessors. 251 // Only allow API accessors.
(...skipping 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 v8::Utils::ToLocal(value_handle), 1499 v8::Utils::ToLocal(value_handle),
1493 info); 1500 info);
1494 } 1501 }
1495 RETURN_IF_SCHEDULED_EXCEPTION(); 1502 RETURN_IF_SCHEDULED_EXCEPTION();
1496 return *value_handle; 1503 return *value_handle;
1497 } 1504 }
1498 1505
1499 if (structure->IsFixedArray()) { 1506 if (structure->IsFixedArray()) {
1500 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); 1507 Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
1501 if (setter->IsJSFunction()) { 1508 if (setter->IsJSFunction()) {
1502 Handle<JSFunction> fun(JSFunction::cast(setter)); 1509 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
1503 Handle<JSObject> self(this);
1504 bool has_pending_exception;
1505 Object** argv[] = { value_handle.location() };
1506 Execution::Call(fun, self, 1, argv, &has_pending_exception);
1507 // Check for pending exception and return the result.
1508 if (has_pending_exception) return Failure::Exception();
1509 } else { 1510 } else {
1510 Handle<String> key(name); 1511 Handle<String> key(name);
1511 Handle<Object> holder_handle(holder); 1512 Handle<Object> holder_handle(holder);
1512 Handle<Object> args[2] = { key, holder_handle }; 1513 Handle<Object> args[2] = { key, holder_handle };
1513 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", 1514 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
1514 HandleVector(args, 2))); 1515 HandleVector(args, 2)));
1515 } 1516 }
1516 return *value_handle;
1517 } 1517 }
1518 1518
1519 UNREACHABLE(); 1519 UNREACHABLE();
1520 return 0; 1520 return 0;
1521 } 1521 }
1522 1522
1523 1523
1524 Object* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter,
1525 Object* value) {
1526 Handle<Object> value_handle(value);
1527 Handle<JSFunction> fun(JSFunction::cast(setter));
1528 Handle<JSObject> self(this);
1529 bool has_pending_exception;
1530 Object** argv[] = { value_handle.location() };
1531 Execution::Call(fun, self, 1, argv, &has_pending_exception);
1532 // Check for pending exception and return the result.
1533 if (has_pending_exception) return Failure::Exception();
1534 return *value_handle;
1535 }
1536
1524 void JSObject::LookupCallbackSetterInPrototypes(String* name, 1537 void JSObject::LookupCallbackSetterInPrototypes(String* name,
1525 LookupResult* result) { 1538 LookupResult* result) {
1526 for (Object* pt = GetPrototype(); 1539 for (Object* pt = GetPrototype();
1527 pt != Heap::null_value(); 1540 pt != Heap::null_value();
1528 pt = pt->GetPrototype()) { 1541 pt = pt->GetPrototype()) {
1529 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); 1542 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
1530 if (result->IsValid()) { 1543 if (result->IsValid()) {
1531 if (!result->IsTransitionType() && result->IsReadOnly()) { 1544 if (!result->IsTransitionType() && result->IsReadOnly()) {
1532 result->NotFound(); 1545 result->NotFound();
1533 return; 1546 return;
1534 } 1547 }
1535 if (result->type() == CALLBACKS) { 1548 if (result->type() == CALLBACKS) {
1536 return; 1549 return;
1537 } 1550 }
1538 } 1551 }
1539 } 1552 }
1540 result->NotFound(); 1553 result->NotFound();
1541 } 1554 }
1542 1555
1543 1556
1557 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
1558 for (Object* pt = GetPrototype();
1559 pt != Heap::null_value();
1560 pt = pt->GetPrototype()) {
1561 if (JSObject::cast(pt)->HasFastElements()) continue;
1562 Dictionary* dictionary = JSObject::cast(pt)->element_dictionary();
1563 int entry = dictionary->FindNumberEntry(index);
1564 if (entry != -1) {
1565 Object* element = dictionary->ValueAt(entry);
1566 PropertyDetails details = dictionary->DetailsAt(entry);
1567 if (details.type() == CALLBACKS) {
1568 // Only accessors allowed as elements.
1569 return FixedArray::cast(element)->get(kSetterIndex);
1570 }
1571 }
1572 }
1573 return Heap::undefined_value();
1574 }
1575
1576
1544 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { 1577 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
1545 DescriptorArray* descriptors = map()->instance_descriptors(); 1578 DescriptorArray* descriptors = map()->instance_descriptors();
1546 int number = descriptors->Search(name); 1579 int number = descriptors->Search(name);
1547 if (number != DescriptorArray::kNotFound) { 1580 if (number != DescriptorArray::kNotFound) {
1548 result->DescriptorResult(this, descriptors->GetDetails(number), number); 1581 result->DescriptorResult(this, descriptors->GetDetails(number), number);
1549 } else { 1582 } else {
1550 result->NotFound(); 1583 result->NotFound();
1551 } 1584 }
1552 } 1585 }
1553 1586
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
2489 // Check access rights if needed. 2522 // Check access rights if needed.
2490 if (IsAccessCheckNeeded() && 2523 if (IsAccessCheckNeeded() &&
2491 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { 2524 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
2492 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); 2525 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
2493 return Heap::undefined_value(); 2526 return Heap::undefined_value();
2494 } 2527 }
2495 2528
2496 // Try to flatten before operating on the string. 2529 // Try to flatten before operating on the string.
2497 name->TryFlattenIfNotFlat(StringShape(name)); 2530 name->TryFlattenIfNotFlat(StringShape(name));
2498 2531
2499 // Make sure name is not an index.
2500 uint32_t index;
2501 if (name->AsArrayIndex(&index)) return Heap::undefined_value();
2502
2503 // Check if there is an API defined callback object which prohibits 2532 // Check if there is an API defined callback object which prohibits
2504 // callback overwriting in this object or it's prototype chain. 2533 // callback overwriting in this object or it's prototype chain.
2505 // This mechanism is needed for instance in a browser setting, where 2534 // This mechanism is needed for instance in a browser setting, where
2506 // certain accessors such as window.location should not be allowed 2535 // certain accessors such as window.location should not be allowed
2507 // to be overwritten because allowing overwriting could potentially 2536 // to be overwritten because allowing overwriting could potentially
2508 // cause security problems. 2537 // cause security problems.
2509 LookupResult callback_result; 2538 LookupResult callback_result;
2510 LookupCallback(name, &callback_result); 2539 LookupCallback(name, &callback_result);
2511 if (callback_result.IsValid()) { 2540 if (callback_result.IsValid()) {
2512 Object* obj = callback_result.GetCallbackObject(); 2541 Object* obj = callback_result.GetCallbackObject();
2513 if (obj->IsAccessorInfo() && 2542 if (obj->IsAccessorInfo() &&
2514 AccessorInfo::cast(obj)->prohibits_overwriting()) { 2543 AccessorInfo::cast(obj)->prohibits_overwriting()) {
2515 return Heap::undefined_value(); 2544 return Heap::undefined_value();
2516 } 2545 }
2517 } 2546 }
2518 2547
2519 // Lookup the name. 2548 uint32_t index;
2520 LookupResult result; 2549 bool is_element = name->AsArrayIndex(&index);
2521 LocalLookup(name, &result); 2550 if (is_element && IsJSArray()) return Heap::undefined_value();
2522 if (result.IsValid()) { 2551
2523 if (result.IsReadOnly()) return Heap::undefined_value(); 2552 if (is_element) {
2524 if (result.type() == CALLBACKS) { 2553 // Lookup the index.
2525 Object* obj = result.GetCallbackObject(); 2554 if (!HasFastElements()) {
2526 if (obj->IsFixedArray()) return obj; 2555 Dictionary* dictionary = element_dictionary();
2556 int entry = dictionary->FindNumberEntry(index);
2557 if (entry != -1) {
2558 Object* result = dictionary->ValueAt(entry);
2559 PropertyDetails details = dictionary->DetailsAt(entry);
2560 if (details.IsReadOnly()) return Heap::undefined_value();
2561 if (details.type() == CALLBACKS) {
2562 // Only accessors allowed as elements.
2563 ASSERT(result->IsFixedArray());
2564 return result;
2565 }
2566 }
2567 }
2568 } else {
2569 // Lookup the name.
2570 LookupResult result;
2571 LocalLookup(name, &result);
2572 if (result.IsValid()) {
2573 if (result.IsReadOnly()) return Heap::undefined_value();
2574 if (result.type() == CALLBACKS) {
2575 Object* obj = result.GetCallbackObject();
2576 if (obj->IsFixedArray()) return obj;
2577 }
2527 } 2578 }
2528 } 2579 }
2529 2580
2530 // Normalize object to make this operation simple. 2581 // Allocate the fixed array to hold getter and setter.
2531 Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); 2582 Object* structure = Heap::AllocateFixedArray(2, TENURED);
2532 if (ok->IsFailure()) return ok; 2583 if (structure->IsFailure()) return structure;
2584 PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
2533 2585
2534 // Allocate the fixed array to hold getter and setter. 2586 if (is_element) {
2535 Object* array = Heap::AllocateFixedArray(2, TENURED); 2587 // Normalize object to make this operation simple.
2536 if (array->IsFailure()) return array; 2588 Object* ok = NormalizeElements();
2589 if (ok->IsFailure()) return ok;
2537 2590
2538 // Update the dictionary with the new CALLBACKS property. 2591 // Update the dictionary with the new CALLBACKS property.
2539 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 2592 Object* dict =
2540 Object* dict = 2593 element_dictionary()->SetOrAddNumberEntry(index, structure, details);
2541 property_dictionary()->SetOrAddStringEntry(name, array, details); 2594 if (dict->IsFailure()) return dict;
2542 if (dict->IsFailure()) return dict;
2543 2595
2544 // Set the potential new dictionary on the object. 2596 // If name is an index we need to stay in slow case.
2545 set_properties(Dictionary::cast(dict)); 2597 Dictionary* elements = Dictionary::cast(dict);
2546 return array; 2598 elements->set_requires_slow_elements();
2599 // Set the potential new dictionary on the object.
2600 set_elements(Dictionary::cast(dict));
2601
2602 // Update the array length if this JSObject is an array.
Mads Ager (chromium) 2009/03/13 10:27:14 Since we do not do this for arrays, we can remove
olehougaard 2009/03/13 11:39:46 Fixed.
2603 if (IsJSArray()) {
2604 JSArray* array = JSArray::cast(this);
2605 Object* return_value =
2606 array->JSArrayUpdateLengthFromIndex(index, structure);
2607 if (return_value->IsFailure()) return return_value;
2608 }
2609 } else {
2610 // Normalize object to make this operation simple.
2611 Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
2612 if (ok->IsFailure()) return ok;
2613
2614 // Update the dictionary with the new CALLBACKS property.
2615 Object* dict =
2616 property_dictionary()->SetOrAddStringEntry(name, structure, details);
2617 if (dict->IsFailure()) return dict;
2618
2619 // Set the potential new dictionary on the object.
2620 set_properties(Dictionary::cast(dict));
2621 }
2622
2623 return structure;
2547 } 2624 }
2548 2625
2549 2626
2550 Object* JSObject::DefineAccessor(String* name, bool is_getter, JSFunction* fun, 2627 Object* JSObject::DefineAccessor(String* name, bool is_getter, JSFunction* fun,
2551 PropertyAttributes attributes) { 2628 PropertyAttributes attributes) {
2552 // Check access rights if needed. 2629 // Check access rights if needed.
2553 if (IsAccessCheckNeeded() && 2630 if (IsAccessCheckNeeded() &&
2554 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { 2631 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
2555 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); 2632 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
2556 return Heap::undefined_value(); 2633 return Heap::undefined_value();
(...skipping 19 matching lines...) Expand all
2576 // interceptor calls. 2653 // interceptor calls.
2577 AssertNoContextChange ncc; 2654 AssertNoContextChange ncc;
2578 2655
2579 // Check access rights if needed. 2656 // Check access rights if needed.
2580 if (IsAccessCheckNeeded() && 2657 if (IsAccessCheckNeeded() &&
2581 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { 2658 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
2582 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); 2659 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
2583 return Heap::undefined_value(); 2660 return Heap::undefined_value();
2584 } 2661 }
2585 2662
2586 // Make sure name is not an index. 2663 // Make the lookup and include prototypes.
2664 int accessor_index = is_getter ? kGetterIndex : kSetterIndex;
2587 uint32_t index; 2665 uint32_t index;
2588 if (name->AsArrayIndex(&index)) return Heap::undefined_value(); 2666 if (name->AsArrayIndex(&index)) {
2589 2667 for (Object* obj = this;
2590 // Make the lookup and include prototypes. 2668 obj != Heap::null_value();
2591 for (Object* obj = this; 2669 obj = JSObject::cast(obj)->GetPrototype()) {
2592 obj != Heap::null_value(); 2670 JSObject* jsObject = JSObject::cast(obj);
2593 obj = JSObject::cast(obj)->GetPrototype()) { 2671 if (!jsObject->HasFastElements()) {
2594 LookupResult result; 2672 Dictionary* dictionary = jsObject->element_dictionary();
2595 JSObject::cast(obj)->LocalLookup(name, &result); 2673 int entry = dictionary->FindNumberEntry(index);
2596 if (result.IsValid()) { 2674 if (entry != -1) {
2597 if (result.IsReadOnly()) return Heap::undefined_value(); 2675 Object* element = dictionary->ValueAt(entry);
2598 if (result.type() == CALLBACKS) { 2676 PropertyDetails details = dictionary->DetailsAt(entry);
2599 Object* obj = result.GetCallbackObject(); 2677 if (details.type() == CALLBACKS) {
2600 if (obj->IsFixedArray()) { 2678 // Only accessors allowed as elements.
2601 return FixedArray::cast(obj)->get(is_getter 2679 return FixedArray::cast(element)->get(accessor_index);
2602 ? kGetterIndex 2680 }
2603 : kSetterIndex); 2681 }
2682 }
2683 }
2684 } else {
2685 for (Object* obj = this;
2686 obj != Heap::null_value();
2687 obj = JSObject::cast(obj)->GetPrototype()) {
2688 LookupResult result;
2689 JSObject::cast(obj)->LocalLookup(name, &result);
2690 if (result.IsValid()) {
2691 if (result.IsReadOnly()) return Heap::undefined_value();
2692 if (result.type() == CALLBACKS) {
2693 Object* obj = result.GetCallbackObject();
2694 if (obj->IsFixedArray()) {
2695 return FixedArray::cast(obj)->get(accessor_index);
2696 }
2604 } 2697 }
2605 } 2698 }
2606 } 2699 }
2607 } 2700 }
2608 return Heap::undefined_value(); 2701 return Heap::undefined_value();
2609 } 2702 }
2610 2703
2611 2704
2612 Object* JSObject::SlowReverseLookup(Object* value) { 2705 Object* JSObject::SlowReverseLookup(Object* value) {
2613 if (HasFastProperties()) { 2706 if (HasFastProperties()) {
(...skipping 2555 matching lines...) Expand 10 before | Expand all | Expand 10 after
5169 5262
5170 // Adding n elements in fast case is O(n*n). 5263 // Adding n elements in fast case is O(n*n).
5171 // Note: revisit design to have dual undefined values to capture absent 5264 // Note: revisit design to have dual undefined values to capture absent
5172 // elements. 5265 // elements.
5173 Object* JSObject::SetFastElement(uint32_t index, Object* value) { 5266 Object* JSObject::SetFastElement(uint32_t index, Object* value) {
5174 ASSERT(HasFastElements()); 5267 ASSERT(HasFastElements());
5175 5268
5176 FixedArray* elms = FixedArray::cast(elements()); 5269 FixedArray* elms = FixedArray::cast(elements());
5177 uint32_t elms_length = static_cast<uint32_t>(elms->length()); 5270 uint32_t elms_length = static_cast<uint32_t>(elms->length());
5178 5271
5272 if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
5273 Object* setter = LookupCallbackSetterInPrototypes(index);
5274 if (setter->IsJSFunction()) {
5275 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
5276 }
5277 }
5278
5179 // Check whether there is extra space in fixed array.. 5279 // Check whether there is extra space in fixed array..
5180 if (index < elms_length) { 5280 if (index < elms_length) {
5181 elms->set(index, value); 5281 elms->set(index, value);
5182 if (IsJSArray()) { 5282 if (IsJSArray()) {
5183 // Update the length of the array if needed. 5283 // Update the length of the array if needed.
5184 uint32_t array_length = 0; 5284 uint32_t array_length = 0;
5185 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), 5285 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
5186 &array_length)); 5286 &array_length));
5187 if (index >= array_length) { 5287 if (index >= array_length) {
5188 JSArray::cast(this)->set_length(Smi::FromInt(index + 1), 5288 JSArray::cast(this)->set_length(Smi::FromInt(index + 1),
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
5238 5338
5239 // Fast case. 5339 // Fast case.
5240 if (HasFastElements()) return SetFastElement(index, value); 5340 if (HasFastElements()) return SetFastElement(index, value);
5241 5341
5242 // Dictionary case. 5342 // Dictionary case.
5243 ASSERT(!HasFastElements()); 5343 ASSERT(!HasFastElements());
5244 5344
5245 // Insert element in the dictionary. 5345 // Insert element in the dictionary.
5246 FixedArray* elms = FixedArray::cast(elements()); 5346 FixedArray* elms = FixedArray::cast(elements());
5247 Dictionary* dictionary = Dictionary::cast(elms); 5347 Dictionary* dictionary = Dictionary::cast(elms);
5248 Object* result = dictionary->AtNumberPut(index, value); 5348
5249 if (result->IsFailure()) return result; 5349 int entry = dictionary->FindNumberEntry(index);
5250 if (elms != FixedArray::cast(result)) { 5350 if (entry != -1) {
5251 set_elements(FixedArray::cast(result)); 5351 Object* element = dictionary->ValueAt(entry);
5352 PropertyDetails details = dictionary->DetailsAt(entry);
5353 if (details.type() == CALLBACKS) {
5354 // Only accessors allowed as elements.
5355 FixedArray* structure = FixedArray::cast(element);
5356 if (structure->get(kSetterIndex)->IsJSFunction()) {
Mads Ager (chromium) 2009/03/13 10:27:14 I believe that we throw exceptions when setting na
olehougaard 2009/03/13 11:39:46 That's true. I've fixed it and added a test for it
5357 JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex));
5358 return SetPropertyWithDefinedSetter(setter, value);
5359 }
5360 } else {
5361 dictionary->UpdateMaxNumberKey(index);
5362 dictionary->ValueAtPut(entry, value);
5363 }
5364 } else {
5365 // Index not already used. Look for an accessor in the prototype chain.
5366 if (!IsJSArray()) {
5367 Object* setter = LookupCallbackSetterInPrototypes(index);
5368 if (setter->IsJSFunction()) {
5369 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
5370 }
5371 }
5372 Object* result = dictionary->AtNumberPut(index, value);
5373 if (result->IsFailure()) return result;
5374 if (elms != FixedArray::cast(result)) {
5375 set_elements(FixedArray::cast(result));
5376 }
5252 } 5377 }
5253 5378
5254 // Update the array length if this JSObject is an array. 5379 // Update the array length if this JSObject is an array.
5255 if (IsJSArray()) { 5380 if (IsJSArray()) {
5256 JSArray* array = JSArray::cast(this); 5381 JSArray* array = JSArray::cast(this);
5257 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, value); 5382 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, value);
5258 if (return_value->IsFailure()) return return_value; 5383 if (return_value->IsFailure()) return return_value;
5259 } 5384 }
5260 5385
5261 // Attempt to put this object back in fast case. 5386 // Attempt to put this object back in fast case.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
5374 if (HasFastElements()) { 5499 if (HasFastElements()) {
5375 FixedArray* elms = FixedArray::cast(elements()); 5500 FixedArray* elms = FixedArray::cast(elements());
5376 if (index < static_cast<uint32_t>(elms->length())) { 5501 if (index < static_cast<uint32_t>(elms->length())) {
5377 Object* value = elms->get(index); 5502 Object* value = elms->get(index);
5378 if (!value->IsTheHole()) return value; 5503 if (!value->IsTheHole()) return value;
5379 } 5504 }
5380 } else { 5505 } else {
5381 Dictionary* dictionary = element_dictionary(); 5506 Dictionary* dictionary = element_dictionary();
5382 int entry = dictionary->FindNumberEntry(index); 5507 int entry = dictionary->FindNumberEntry(index);
5383 if (entry != -1) { 5508 if (entry != -1) {
5384 return dictionary->ValueAt(entry); 5509 Object* element = dictionary->ValueAt(entry);
5510 PropertyDetails details = dictionary->DetailsAt(entry);
5511 if (details.type() == CALLBACKS) {
5512 // Only accessors allowed as elements.
5513 FixedArray* structure = FixedArray::cast(element);
5514 Object* getter = structure->get(kGetterIndex);
5515 if (getter->IsJSFunction()) {
5516 return GetPropertyWithDefinedGetter(receiver,
5517 JSFunction::cast(getter));
5518 }
5519 }
5520 return element;
5385 } 5521 }
5386 } 5522 }
5387 5523
5388 Object* pt = GetPrototype(); 5524 Object* pt = GetPrototype();
5389 if (pt == Heap::null_value()) return Heap::undefined_value(); 5525 if (pt == Heap::null_value()) return Heap::undefined_value();
5390 return pt->GetElementWithReceiver(receiver, index); 5526 return pt->GetElementWithReceiver(receiver, index);
5391 } 5527 }
5392 5528
5393 5529
5394 bool JSObject::HasDenseElements() { 5530 bool JSObject::HasDenseElements() {
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
5889 return hash; 6025 return hash;
5890 } 6026 }
5891 6027
5892 6028
5893 // The NumberKey uses carries the uint32_t as key. 6029 // The NumberKey uses carries the uint32_t as key.
5894 // This avoids allocation in HasProperty. 6030 // This avoids allocation in HasProperty.
5895 class NumberKey : public HashTableKey { 6031 class NumberKey : public HashTableKey {
5896 public: 6032 public:
5897 explicit NumberKey(uint32_t number) : number_(number) { } 6033 explicit NumberKey(uint32_t number) : number_(number) { }
5898 6034
5899 private:
5900 bool IsMatch(Object* number) { 6035 bool IsMatch(Object* number) {
5901 return number_ == ToUint32(number); 6036 return number_ == ToUint32(number);
5902 } 6037 }
5903 6038
5904 uint32_t Hash() { return ComputeIntegerHash(number_); } 6039 uint32_t Hash() { return ComputeIntegerHash(number_); }
5905 6040
5906 HashFunction GetHashFunction() { return NumberHash; } 6041 HashFunction GetHashFunction() { return NumberHash; }
5907 6042
5908 Object* GetObject() { 6043 Object* GetObject() {
5909 return Heap::NumberFromDouble(number_); 6044 return Heap::NumberFromDouble(number_);
5910 } 6045 }
5911 6046
6047 bool IsStringKey() { return false; }
6048
6049 private:
5912 static uint32_t NumberHash(Object* obj) { 6050 static uint32_t NumberHash(Object* obj) {
5913 return ComputeIntegerHash(ToUint32(obj)); 6051 return ComputeIntegerHash(ToUint32(obj));
5914 } 6052 }
5915 6053
5916 static uint32_t ToUint32(Object* obj) { 6054 static uint32_t ToUint32(Object* obj) {
5917 ASSERT(obj->IsNumber()); 6055 ASSERT(obj->IsNumber());
5918 return static_cast<uint32_t>(obj->Number()); 6056 return static_cast<uint32_t>(obj->Number());
5919 } 6057 }
5920 6058
5921 bool IsStringKey() { return false; }
5922
5923 uint32_t number_; 6059 uint32_t number_;
5924 }; 6060 };
5925 6061
5926 6062
5927 // StringKey simply carries a string object as key. 6063 // StringKey simply carries a string object as key.
5928 class StringKey : public HashTableKey { 6064 class StringKey : public HashTableKey {
5929 public: 6065 public:
5930 explicit StringKey(String* string) : string_(string) { } 6066 explicit StringKey(String* string) : string_(string) { }
5931 6067
5932 bool IsMatch(Object* string) { 6068 bool IsMatch(Object* string) {
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after
6709 } 6845 }
6710 6846
6711 6847
6712 void Dictionary::UpdateMaxNumberKey(uint32_t key) { 6848 void Dictionary::UpdateMaxNumberKey(uint32_t key) {
6713 // If the dictionary requires slow elements an element has already 6849 // If the dictionary requires slow elements an element has already
6714 // been added at a high index. 6850 // been added at a high index.
6715 if (requires_slow_elements()) return; 6851 if (requires_slow_elements()) return;
6716 // Check if this index is high enough that we should require slow 6852 // Check if this index is high enough that we should require slow
6717 // elements. 6853 // elements.
6718 if (key > kRequiresSlowElementsLimit) { 6854 if (key > kRequiresSlowElementsLimit) {
6719 set(kMaxNumberKeyIndex, 6855 set_requires_slow_elements();
6720 Smi::FromInt(kRequiresSlowElementsMask),
6721 SKIP_WRITE_BARRIER);
6722 return; 6856 return;
6723 } 6857 }
6724 // Update max key value. 6858 // Update max key value.
6725 Object* max_index_object = get(kMaxNumberKeyIndex); 6859 Object* max_index_object = get(kMaxNumberKeyIndex);
6726 if (!max_index_object->IsSmi() || max_number_key() < key) { 6860 if (!max_index_object->IsSmi() || max_number_key() < key) {
6727 set(kMaxNumberKeyIndex, 6861 set(kMaxNumberKeyIndex,
6728 Smi::FromInt(key << kRequiresSlowElementsTagSize), 6862 Smi::FromInt(key << kRequiresSlowElementsTagSize),
6729 SKIP_WRITE_BARRIER); 6863 SKIP_WRITE_BARRIER);
6730 } 6864 }
6731 } 6865 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
6771 if (entry == -1) return AddStringEntry(key, value, details); 6905 if (entry == -1) return AddStringEntry(key, value, details);
6772 // Preserve enumeration index. 6906 // Preserve enumeration index.
6773 details = PropertyDetails(details.attributes(), 6907 details = PropertyDetails(details.attributes(),
6774 details.type(), 6908 details.type(),
6775 DetailsAt(entry).index()); 6909 DetailsAt(entry).index());
6776 SetEntry(entry, key, value, details); 6910 SetEntry(entry, key, value, details);
6777 return this; 6911 return this;
6778 } 6912 }
6779 6913
6780 6914
6915 Object* Dictionary::SetOrAddNumberEntry(uint32_t key,
6916 Object* value,
6917 PropertyDetails details) {
6918 NumberKey k(key);
6919 int entry = FindEntry(&k);
6920 if (entry == -1) return AddNumberEntry(key, value, details);
6921 // Preserve enumeration index.
6922 details = PropertyDetails(details.attributes(),
6923 details.type(),
6924 DetailsAt(entry).index());
6925 SetEntry(entry, k.GetObject(), value, details);
6926 return this;
6927 }
6928
6929
6781 int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) { 6930 int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) {
6782 int capacity = Capacity(); 6931 int capacity = Capacity();
6783 int result = 0; 6932 int result = 0;
6784 for (int i = 0; i < capacity; i++) { 6933 for (int i = 0; i < capacity; i++) {
6785 Object* k = KeyAt(i); 6934 Object* k = KeyAt(i);
6786 if (IsKey(k)) { 6935 if (IsKey(k)) {
6787 PropertyAttributes attr = DetailsAt(i).attributes(); 6936 PropertyAttributes attr = DetailsAt(i).attributes();
6788 if ((attr & filter) == 0) result++; 6937 if ((attr & filter) == 0) result++;
6789 } 6938 }
6790 } 6939 }
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
7214 // No break point. 7363 // No break point.
7215 if (break_point_objects()->IsUndefined()) return 0; 7364 if (break_point_objects()->IsUndefined()) return 0;
7216 // Single beak point. 7365 // Single beak point.
7217 if (!break_point_objects()->IsFixedArray()) return 1; 7366 if (!break_point_objects()->IsFixedArray()) return 1;
7218 // Multiple break points. 7367 // Multiple break points.
7219 return FixedArray::cast(break_point_objects())->length(); 7368 return FixedArray::cast(break_point_objects())->length();
7220 } 7369 }
7221 7370
7222 7371
7223 } } // namespace v8::internal 7372 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698