Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |