| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 return holder->GetPropertyWithInterceptor(recvr, name, attributes); | 543 return holder->GetPropertyWithInterceptor(recvr, name, attributes); |
| 544 } | 544 } |
| 545 default: | 545 default: |
| 546 UNREACHABLE(); | 546 UNREACHABLE(); |
| 547 return NULL; | 547 return NULL; |
| 548 } | 548 } |
| 549 } | 549 } |
| 550 | 550 |
| 551 | 551 |
| 552 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { | 552 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { |
| 553 // Non-JS objects do not have integer indexed properties. | 553 if (IsJSObject()) { |
| 554 if (!IsJSObject()) return Isolate::Current()->heap()->undefined_value(); | 554 return JSObject::cast(this)->GetElementWithReceiver(receiver, index); |
| 555 return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver), | 555 } |
| 556 index); | 556 |
| 557 Object* holder = NULL; |
| 558 Context* global_context = Isolate::Current()->context()->global_context(); |
| 559 if (IsString()) { |
| 560 holder = global_context->string_function()->instance_prototype(); |
| 561 } else if (IsNumber()) { |
| 562 holder = global_context->number_function()->instance_prototype(); |
| 563 } else if (IsBoolean()) { |
| 564 holder = global_context->boolean_function()->instance_prototype(); |
| 565 } else { |
| 566 // Undefined and null have no indexed properties. |
| 567 ASSERT(IsUndefined() || IsNull()); |
| 568 return HEAP->undefined_value(); |
| 569 } |
| 570 |
| 571 return JSObject::cast(holder)->GetElementWithReceiver(receiver, index); |
| 557 } | 572 } |
| 558 | 573 |
| 559 | 574 |
| 560 Object* Object::GetPrototype() { | 575 Object* Object::GetPrototype() { |
| 561 // The object is either a number, a string, a boolean, or a real JS object. | 576 // The object is either a number, a string, a boolean, or a real JS object. |
| 562 if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); | 577 if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); |
| 563 Heap* heap = Isolate::Current()->heap(); | 578 Heap* heap = Isolate::Current()->heap(); |
| 564 Context* context = heap->isolate()->context()->global_context(); | 579 Context* context = heap->isolate()->context()->global_context(); |
| 565 | 580 |
| 566 if (IsNumber()) return context->number_function()->instance_prototype(); | 581 if (IsNumber()) return context->number_function()->instance_prototype(); |
| (...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 } | 1466 } |
| 1452 } | 1467 } |
| 1453 } | 1468 } |
| 1454 return AddSlowProperty(name, value, attributes); | 1469 return AddSlowProperty(name, value, attributes); |
| 1455 } | 1470 } |
| 1456 | 1471 |
| 1457 | 1472 |
| 1458 MaybeObject* JSObject::SetPropertyPostInterceptor( | 1473 MaybeObject* JSObject::SetPropertyPostInterceptor( |
| 1459 String* name, | 1474 String* name, |
| 1460 Object* value, | 1475 Object* value, |
| 1461 PropertyAttributes attributes) { | 1476 PropertyAttributes attributes, |
| 1477 StrictModeFlag strict) { |
| 1462 // Check local property, ignore interceptor. | 1478 // Check local property, ignore interceptor. |
| 1463 LookupResult result; | 1479 LookupResult result; |
| 1464 LocalLookupRealNamedProperty(name, &result); | 1480 LocalLookupRealNamedProperty(name, &result); |
| 1465 if (result.IsFound()) { | 1481 if (result.IsFound()) { |
| 1466 // An existing property, a map transition or a null descriptor was | 1482 // An existing property, a map transition or a null descriptor was |
| 1467 // found. Use set property to handle all these cases. | 1483 // found. Use set property to handle all these cases. |
| 1468 return SetProperty(&result, name, value, attributes); | 1484 return SetProperty(&result, name, value, attributes, strict); |
| 1469 } | 1485 } |
| 1470 // Add a new real property. | 1486 // Add a new real property. |
| 1471 return AddProperty(name, value, attributes); | 1487 return AddProperty(name, value, attributes); |
| 1472 } | 1488 } |
| 1473 | 1489 |
| 1474 | 1490 |
| 1475 MaybeObject* JSObject::ReplaceSlowProperty(String* name, | 1491 MaybeObject* JSObject::ReplaceSlowProperty(String* name, |
| 1476 Object* value, | 1492 Object* value, |
| 1477 PropertyAttributes attributes) { | 1493 PropertyAttributes attributes) { |
| 1478 StringDictionary* dictionary = property_dictionary(); | 1494 StringDictionary* dictionary = property_dictionary(); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1584 set_properties(FixedArray::cast(new_properties)); | 1600 set_properties(FixedArray::cast(new_properties)); |
| 1585 } | 1601 } |
| 1586 return FastPropertyAtPut(index, new_value); | 1602 return FastPropertyAtPut(index, new_value); |
| 1587 } | 1603 } |
| 1588 | 1604 |
| 1589 | 1605 |
| 1590 | 1606 |
| 1591 MaybeObject* JSObject::SetPropertyWithInterceptor( | 1607 MaybeObject* JSObject::SetPropertyWithInterceptor( |
| 1592 String* name, | 1608 String* name, |
| 1593 Object* value, | 1609 Object* value, |
| 1594 PropertyAttributes attributes) { | 1610 PropertyAttributes attributes, |
| 1611 StrictModeFlag strict) { |
| 1595 Isolate* isolate = GetIsolate(); | 1612 Isolate* isolate = GetIsolate(); |
| 1596 HandleScope scope(isolate); | 1613 HandleScope scope(isolate); |
| 1597 Handle<JSObject> this_handle(this); | 1614 Handle<JSObject> this_handle(this); |
| 1598 Handle<String> name_handle(name); | 1615 Handle<String> name_handle(name); |
| 1599 Handle<Object> value_handle(value, isolate); | 1616 Handle<Object> value_handle(value, isolate); |
| 1600 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 1617 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 1601 if (!interceptor->setter()->IsUndefined()) { | 1618 if (!interceptor->setter()->IsUndefined()) { |
| 1602 LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 1619 LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); |
| 1603 CustomArguments args(isolate, interceptor->data(), this, this); | 1620 CustomArguments args(isolate, interceptor->data(), this, this); |
| 1604 v8::AccessorInfo info(args.end()); | 1621 v8::AccessorInfo info(args.end()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1615 result = setter(v8::Utils::ToLocal(name_handle), | 1632 result = setter(v8::Utils::ToLocal(name_handle), |
| 1616 v8::Utils::ToLocal(value_unhole), | 1633 v8::Utils::ToLocal(value_unhole), |
| 1617 info); | 1634 info); |
| 1618 } | 1635 } |
| 1619 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 1636 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1620 if (!result.IsEmpty()) return *value_handle; | 1637 if (!result.IsEmpty()) return *value_handle; |
| 1621 } | 1638 } |
| 1622 MaybeObject* raw_result = | 1639 MaybeObject* raw_result = |
| 1623 this_handle->SetPropertyPostInterceptor(*name_handle, | 1640 this_handle->SetPropertyPostInterceptor(*name_handle, |
| 1624 *value_handle, | 1641 *value_handle, |
| 1625 attributes); | 1642 attributes, |
| 1643 strict); |
| 1626 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 1644 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1627 return raw_result; | 1645 return raw_result; |
| 1628 } | 1646 } |
| 1629 | 1647 |
| 1630 | 1648 |
| 1631 MaybeObject* JSObject::SetProperty(String* name, | 1649 MaybeObject* JSObject::SetProperty(String* name, |
| 1632 Object* value, | 1650 Object* value, |
| 1633 PropertyAttributes attributes) { | 1651 PropertyAttributes attributes, |
| 1652 StrictModeFlag strict) { |
| 1634 LookupResult result; | 1653 LookupResult result; |
| 1635 LocalLookup(name, &result); | 1654 LocalLookup(name, &result); |
| 1636 return SetProperty(&result, name, value, attributes); | 1655 return SetProperty(&result, name, value, attributes, strict); |
| 1637 } | 1656 } |
| 1638 | 1657 |
| 1639 | 1658 |
| 1640 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 1659 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, |
| 1641 String* name, | 1660 String* name, |
| 1642 Object* value, | 1661 Object* value, |
| 1643 JSObject* holder) { | 1662 JSObject* holder) { |
| 1644 Isolate* isolate = GetIsolate(); | 1663 Isolate* isolate = GetIsolate(); |
| 1645 HandleScope scope(isolate); | 1664 HandleScope scope(isolate); |
| 1646 | 1665 |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1915 HandleScope scope; | 1934 HandleScope scope; |
| 1916 Handle<Object> value_handle(value); | 1935 Handle<Object> value_handle(value); |
| 1917 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 1936 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 1918 return *value_handle; | 1937 return *value_handle; |
| 1919 } | 1938 } |
| 1920 | 1939 |
| 1921 | 1940 |
| 1922 MaybeObject* JSObject::SetProperty(LookupResult* result, | 1941 MaybeObject* JSObject::SetProperty(LookupResult* result, |
| 1923 String* name, | 1942 String* name, |
| 1924 Object* value, | 1943 Object* value, |
| 1925 PropertyAttributes attributes) { | 1944 PropertyAttributes attributes, |
| 1945 StrictModeFlag strict) { |
| 1926 Heap* heap = GetHeap(); | 1946 Heap* heap = GetHeap(); |
| 1927 // Make sure that the top context does not change when doing callbacks or | 1947 // Make sure that the top context does not change when doing callbacks or |
| 1928 // interceptor calls. | 1948 // interceptor calls. |
| 1929 AssertNoContextChange ncc; | 1949 AssertNoContextChange ncc; |
| 1930 | 1950 |
| 1931 // Optimization for 2-byte strings often used as keys in a decompression | 1951 // Optimization for 2-byte strings often used as keys in a decompression |
| 1932 // dictionary. We make these short keys into symbols to avoid constantly | 1952 // dictionary. We make these short keys into symbols to avoid constantly |
| 1933 // reallocating them. | 1953 // reallocating them. |
| 1934 if (!name->IsSymbol() && name->length() <= 2) { | 1954 if (!name->IsSymbol() && name->length() <= 2) { |
| 1935 Object* symbol_version; | 1955 Object* symbol_version; |
| 1936 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); | 1956 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); |
| 1937 if (maybe_symbol_version->ToObject(&symbol_version)) { | 1957 if (maybe_symbol_version->ToObject(&symbol_version)) { |
| 1938 name = String::cast(symbol_version); | 1958 name = String::cast(symbol_version); |
| 1939 } | 1959 } |
| 1940 } | 1960 } |
| 1941 } | 1961 } |
| 1942 | 1962 |
| 1943 // Check access rights if needed. | 1963 // Check access rights if needed. |
| 1944 if (IsAccessCheckNeeded() | 1964 if (IsAccessCheckNeeded() |
| 1945 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1965 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1946 return SetPropertyWithFailedAccessCheck(result, name, value, true); | 1966 return SetPropertyWithFailedAccessCheck(result, name, value, true); |
| 1947 } | 1967 } |
| 1948 | 1968 |
| 1949 if (IsJSGlobalProxy()) { | 1969 if (IsJSGlobalProxy()) { |
| 1950 Object* proto = GetPrototype(); | 1970 Object* proto = GetPrototype(); |
| 1951 if (proto->IsNull()) return value; | 1971 if (proto->IsNull()) return value; |
| 1952 ASSERT(proto->IsJSGlobalObject()); | 1972 ASSERT(proto->IsJSGlobalObject()); |
| 1953 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); | 1973 return JSObject::cast(proto)->SetProperty( |
| 1974 result, name, value, attributes, strict); |
| 1954 } | 1975 } |
| 1955 | 1976 |
| 1956 if (!result->IsProperty() && !IsJSContextExtensionObject()) { | 1977 if (!result->IsProperty() && !IsJSContextExtensionObject()) { |
| 1957 // We could not find a local property so let's check whether there is an | 1978 // We could not find a local property so let's check whether there is an |
| 1958 // accessor that wants to handle the property. | 1979 // accessor that wants to handle the property. |
| 1959 LookupResult accessor_result; | 1980 LookupResult accessor_result; |
| 1960 LookupCallbackSetterInPrototypes(name, &accessor_result); | 1981 LookupCallbackSetterInPrototypes(name, &accessor_result); |
| 1961 if (accessor_result.IsProperty()) { | 1982 if (accessor_result.IsProperty()) { |
| 1962 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), | 1983 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), |
| 1963 name, | 1984 name, |
| 1964 value, | 1985 value, |
| 1965 accessor_result.holder()); | 1986 accessor_result.holder()); |
| 1966 } | 1987 } |
| 1967 } | 1988 } |
| 1968 if (!result->IsFound()) { | 1989 if (!result->IsFound()) { |
| 1969 // Neither properties nor transitions found. | 1990 // Neither properties nor transitions found. |
| 1970 return AddProperty(name, value, attributes); | 1991 return AddProperty(name, value, attributes); |
| 1971 } | 1992 } |
| 1972 if (result->IsReadOnly() && result->IsProperty()) return value; | 1993 if (result->IsReadOnly() && result->IsProperty()) { |
| 1994 if (strict == kStrictMode) { |
| 1995 HandleScope scope; |
| 1996 Handle<String> key(name); |
| 1997 Handle<Object> holder(this); |
| 1998 Handle<Object> args[2] = { key, holder }; |
| 1999 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( |
| 2000 "strict_read_only_property", HandleVector(args, 2))); |
| 2001 |
| 2002 } else { |
| 2003 return value; |
| 2004 } |
| 2005 } |
| 1973 // This is a real property that is not read-only, or it is a | 2006 // This is a real property that is not read-only, or it is a |
| 1974 // transition or null descriptor and there are no setters in the prototypes. | 2007 // transition or null descriptor and there are no setters in the prototypes. |
| 1975 switch (result->type()) { | 2008 switch (result->type()) { |
| 1976 case NORMAL: | 2009 case NORMAL: |
| 1977 return SetNormalizedProperty(result, value); | 2010 return SetNormalizedProperty(result, value); |
| 1978 case FIELD: | 2011 case FIELD: |
| 1979 return FastPropertyAtPut(result->GetFieldIndex(), value); | 2012 return FastPropertyAtPut(result->GetFieldIndex(), value); |
| 1980 case MAP_TRANSITION: | 2013 case MAP_TRANSITION: |
| 1981 if (attributes == result->GetAttributes()) { | 2014 if (attributes == result->GetAttributes()) { |
| 1982 // Only use map transition if the attributes match. | 2015 // Only use map transition if the attributes match. |
| 1983 return AddFastPropertyUsingMap(result->GetTransitionMap(), | 2016 return AddFastPropertyUsingMap(result->GetTransitionMap(), |
| 1984 name, | 2017 name, |
| 1985 value); | 2018 value); |
| 1986 } | 2019 } |
| 1987 return ConvertDescriptorToField(name, value, attributes); | 2020 return ConvertDescriptorToField(name, value, attributes); |
| 1988 case CONSTANT_FUNCTION: | 2021 case CONSTANT_FUNCTION: |
| 1989 // Only replace the function if necessary. | 2022 // Only replace the function if necessary. |
| 1990 if (value == result->GetConstantFunction()) return value; | 2023 if (value == result->GetConstantFunction()) return value; |
| 1991 // Preserve the attributes of this existing property. | 2024 // Preserve the attributes of this existing property. |
| 1992 attributes = result->GetAttributes(); | 2025 attributes = result->GetAttributes(); |
| 1993 return ConvertDescriptorToField(name, value, attributes); | 2026 return ConvertDescriptorToField(name, value, attributes); |
| 1994 case CALLBACKS: | 2027 case CALLBACKS: |
| 1995 return SetPropertyWithCallback(result->GetCallbackObject(), | 2028 return SetPropertyWithCallback(result->GetCallbackObject(), |
| 1996 name, | 2029 name, |
| 1997 value, | 2030 value, |
| 1998 result->holder()); | 2031 result->holder()); |
| 1999 case INTERCEPTOR: | 2032 case INTERCEPTOR: |
| 2000 return SetPropertyWithInterceptor(name, value, attributes); | 2033 return SetPropertyWithInterceptor(name, value, attributes, strict); |
| 2001 case CONSTANT_TRANSITION: { | 2034 case CONSTANT_TRANSITION: { |
| 2002 // If the same constant function is being added we can simply | 2035 // If the same constant function is being added we can simply |
| 2003 // transition to the target map. | 2036 // transition to the target map. |
| 2004 Map* target_map = result->GetTransitionMap(); | 2037 Map* target_map = result->GetTransitionMap(); |
| 2005 DescriptorArray* target_descriptors = target_map->instance_descriptors(); | 2038 DescriptorArray* target_descriptors = target_map->instance_descriptors(); |
| 2006 int number = target_descriptors->SearchWithCache(name); | 2039 int number = target_descriptors->SearchWithCache(name); |
| 2007 ASSERT(number != DescriptorArray::kNotFound); | 2040 ASSERT(number != DescriptorArray::kNotFound); |
| 2008 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); | 2041 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); |
| 2009 JSFunction* function = | 2042 JSFunction* function = |
| 2010 JSFunction::cast(target_descriptors->GetValue(number)); | 2043 JSFunction::cast(target_descriptors->GetValue(number)); |
| (...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2669 case EXTERNAL_INT_ELEMENTS: | 2702 case EXTERNAL_INT_ELEMENTS: |
| 2670 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2703 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 2671 case EXTERNAL_FLOAT_ELEMENTS: | 2704 case EXTERNAL_FLOAT_ELEMENTS: |
| 2672 // Pixel and external array elements cannot be deleted. Just | 2705 // Pixel and external array elements cannot be deleted. Just |
| 2673 // silently ignore here. | 2706 // silently ignore here. |
| 2674 break; | 2707 break; |
| 2675 case DICTIONARY_ELEMENTS: { | 2708 case DICTIONARY_ELEMENTS: { |
| 2676 NumberDictionary* dictionary = element_dictionary(); | 2709 NumberDictionary* dictionary = element_dictionary(); |
| 2677 int entry = dictionary->FindEntry(index); | 2710 int entry = dictionary->FindEntry(index); |
| 2678 if (entry != NumberDictionary::kNotFound) { | 2711 if (entry != NumberDictionary::kNotFound) { |
| 2679 return dictionary->DeleteProperty(entry, mode); | 2712 Object* result = dictionary->DeleteProperty(entry, mode); |
| 2713 if (mode == STRICT_DELETION && result == |
| 2714 isolate->heap()->false_value()) { |
| 2715 // In strict mode, deleting a non-configurable property throws |
| 2716 // exception. dictionary->DeleteProperty will return false_value() |
| 2717 // if a non-configurable property is being deleted. |
| 2718 HandleScope scope; |
| 2719 Handle<Object> i = isolate->factory()->NewNumberFromUint(index); |
| 2720 Handle<Object> args[2] = { i, Handle<Object>(this) }; |
| 2721 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 2722 "strict_delete_property", HandleVector(args, 2))); |
| 2723 } |
| 2680 } | 2724 } |
| 2681 break; | 2725 break; |
| 2682 } | 2726 } |
| 2683 default: | 2727 default: |
| 2684 UNREACHABLE(); | 2728 UNREACHABLE(); |
| 2685 break; | 2729 break; |
| 2686 } | 2730 } |
| 2687 return isolate->heap()->true_value(); | 2731 return isolate->heap()->true_value(); |
| 2688 } | 2732 } |
| 2689 | 2733 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2709 | 2753 |
| 2710 uint32_t index = 0; | 2754 uint32_t index = 0; |
| 2711 if (name->AsArrayIndex(&index)) { | 2755 if (name->AsArrayIndex(&index)) { |
| 2712 return DeleteElement(index, mode); | 2756 return DeleteElement(index, mode); |
| 2713 } else { | 2757 } else { |
| 2714 LookupResult result; | 2758 LookupResult result; |
| 2715 LocalLookup(name, &result); | 2759 LocalLookup(name, &result); |
| 2716 if (!result.IsProperty()) return isolate->heap()->true_value(); | 2760 if (!result.IsProperty()) return isolate->heap()->true_value(); |
| 2717 // Ignore attributes if forcing a deletion. | 2761 // Ignore attributes if forcing a deletion. |
| 2718 if (result.IsDontDelete() && mode != FORCE_DELETION) { | 2762 if (result.IsDontDelete() && mode != FORCE_DELETION) { |
| 2763 if (mode == STRICT_DELETION) { |
| 2764 // Deleting a non-configurable property in strict mode. |
| 2765 HandleScope scope(isolate); |
| 2766 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; |
| 2767 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 2768 "strict_delete_property", HandleVector(args, 2))); |
| 2769 } |
| 2719 return isolate->heap()->false_value(); | 2770 return isolate->heap()->false_value(); |
| 2720 } | 2771 } |
| 2721 // Check for interceptor. | 2772 // Check for interceptor. |
| 2722 if (result.type() == INTERCEPTOR) { | 2773 if (result.type() == INTERCEPTOR) { |
| 2723 // Skip interceptor if forcing a deletion. | 2774 // Skip interceptor if forcing a deletion. |
| 2724 if (mode == FORCE_DELETION) { | 2775 if (mode == FORCE_DELETION) { |
| 2725 return DeletePropertyPostInterceptor(name, mode); | 2776 return DeletePropertyPostInterceptor(name, mode); |
| 2726 } | 2777 } |
| 2727 return DeletePropertyWithInterceptor(name); | 2778 return DeletePropertyWithInterceptor(name); |
| 2728 } | 2779 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2833 return context->extension()->ReferencesObject(obj); | 2884 return context->extension()->ReferencesObject(obj); |
| 2834 } | 2885 } |
| 2835 } | 2886 } |
| 2836 | 2887 |
| 2837 // No references to object. | 2888 // No references to object. |
| 2838 return false; | 2889 return false; |
| 2839 } | 2890 } |
| 2840 | 2891 |
| 2841 | 2892 |
| 2842 MaybeObject* JSObject::PreventExtensions() { | 2893 MaybeObject* JSObject::PreventExtensions() { |
| 2894 Isolate* isolate = GetIsolate(); |
| 2895 if (IsAccessCheckNeeded() && |
| 2896 !isolate->MayNamedAccess(this, |
| 2897 isolate->heap()->undefined_value(), |
| 2898 v8::ACCESS_KEYS)) { |
| 2899 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); |
| 2900 return isolate->heap()->false_value(); |
| 2901 } |
| 2902 |
| 2843 if (IsJSGlobalProxy()) { | 2903 if (IsJSGlobalProxy()) { |
| 2844 Object* proto = GetPrototype(); | 2904 Object* proto = GetPrototype(); |
| 2845 if (proto->IsNull()) return this; | 2905 if (proto->IsNull()) return this; |
| 2846 ASSERT(proto->IsJSGlobalObject()); | 2906 ASSERT(proto->IsJSGlobalObject()); |
| 2847 return JSObject::cast(proto)->PreventExtensions(); | 2907 return JSObject::cast(proto)->PreventExtensions(); |
| 2848 } | 2908 } |
| 2849 | 2909 |
| 2850 // If there are fast elements we normalize. | 2910 // If there are fast elements we normalize. |
| 2851 if (HasFastElements()) { | 2911 if (HasFastElements()) { |
| 2852 Object* ok; | 2912 Object* ok; |
| (...skipping 2670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5523 if (source->IsUndefined()) hash = String::cast(source)->Hash(); | 5583 if (source->IsUndefined()) hash = String::cast(source)->Hash(); |
| 5524 } | 5584 } |
| 5525 hash ^= ComputeIntegerHash(shared()->start_position_and_type()); | 5585 hash ^= ComputeIntegerHash(shared()->start_position_and_type()); |
| 5526 hash += ComputeIntegerHash(shared()->end_position()); | 5586 hash += ComputeIntegerHash(shared()->end_position()); |
| 5527 return hash; | 5587 return hash; |
| 5528 } | 5588 } |
| 5529 | 5589 |
| 5530 | 5590 |
| 5531 bool JSFunction::IsInlineable() { | 5591 bool JSFunction::IsInlineable() { |
| 5532 if (IsBuiltin()) return false; | 5592 if (IsBuiltin()) return false; |
| 5593 SharedFunctionInfo* shared_info = shared(); |
| 5533 // Check that the function has a script associated with it. | 5594 // Check that the function has a script associated with it. |
| 5534 if (!shared()->script()->IsScript()) return false; | 5595 if (!shared_info->script()->IsScript()) return false; |
| 5535 Code* code = shared()->code(); | 5596 if (shared_info->optimization_disabled()) return false; |
| 5597 Code* code = shared_info->code(); |
| 5536 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 5598 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
| 5537 // If we never ran this (unlikely) then lets try to optimize it. | 5599 // If we never ran this (unlikely) then lets try to optimize it. |
| 5538 if (code->kind() != Code::FUNCTION) return true; | 5600 if (code->kind() != Code::FUNCTION) return true; |
| 5539 return code->optimizable(); | 5601 return code->optimizable(); |
| 5540 } | 5602 } |
| 5541 | 5603 |
| 5542 | 5604 |
| 5543 Object* JSFunction::SetInstancePrototype(Object* value) { | 5605 Object* JSFunction::SetInstancePrototype(Object* value) { |
| 5544 ASSERT(value->IsJSObject()); | 5606 ASSERT(value->IsJSObject()); |
| 5545 Heap* heap = GetHeap(); | 5607 Heap* heap = GetHeap(); |
| (...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6338 case INTERCEPTOR: return "INTERCEPTOR"; | 6400 case INTERCEPTOR: return "INTERCEPTOR"; |
| 6339 case MAP_TRANSITION: return "MAP_TRANSITION"; | 6401 case MAP_TRANSITION: return "MAP_TRANSITION"; |
| 6340 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; | 6402 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; |
| 6341 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; | 6403 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; |
| 6342 } | 6404 } |
| 6343 UNREACHABLE(); | 6405 UNREACHABLE(); |
| 6344 return NULL; | 6406 return NULL; |
| 6345 } | 6407 } |
| 6346 | 6408 |
| 6347 | 6409 |
| 6410 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { |
| 6411 const char* name = NULL; |
| 6412 switch (kind) { |
| 6413 case CALL_IC: |
| 6414 if (extra == STRING_INDEX_OUT_OF_BOUNDS) { |
| 6415 name = "STRING_INDEX_OUT_OF_BOUNDS"; |
| 6416 } |
| 6417 break; |
| 6418 case STORE_IC: |
| 6419 case KEYED_STORE_IC: |
| 6420 if (extra == kStrictMode) { |
| 6421 name = "STRICT"; |
| 6422 } |
| 6423 break; |
| 6424 default: |
| 6425 break; |
| 6426 } |
| 6427 if (name != NULL) { |
| 6428 PrintF(out, "extra_ic_state = %s\n", name); |
| 6429 } else { |
| 6430 PrintF(out, "etra_ic_state = %d\n", extra); |
| 6431 } |
| 6432 } |
| 6433 |
| 6434 |
| 6348 void Code::Disassemble(const char* name, FILE* out) { | 6435 void Code::Disassemble(const char* name, FILE* out) { |
| 6349 PrintF(out, "kind = %s\n", Kind2String(kind())); | 6436 PrintF(out, "kind = %s\n", Kind2String(kind())); |
| 6350 if (is_inline_cache_stub()) { | 6437 if (is_inline_cache_stub()) { |
| 6351 PrintF(out, "ic_state = %s\n", ICState2String(ic_state())); | 6438 PrintF(out, "ic_state = %s\n", ICState2String(ic_state())); |
| 6439 PrintExtraICState(out, kind(), extra_ic_state()); |
| 6352 PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); | 6440 PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); |
| 6353 if (ic_state() == MONOMORPHIC) { | 6441 if (ic_state() == MONOMORPHIC) { |
| 6354 PrintF(out, "type = %s\n", PropertyType2String(type())); | 6442 PrintF(out, "type = %s\n", PropertyType2String(type())); |
| 6355 } | 6443 } |
| 6356 } | 6444 } |
| 6357 if ((name != NULL) && (name[0] != '\0')) { | 6445 if ((name != NULL) && (name[0] != '\0')) { |
| 6358 PrintF(out, "name = %s\n", name); | 6446 PrintF(out, "name = %s\n", name); |
| 6359 } | 6447 } |
| 6360 if (kind() == OPTIMIZED_FUNCTION) { | 6448 if (kind() == OPTIMIZED_FUNCTION) { |
| 6361 PrintF(out, "stack_slots = %d\n", stack_slots()); | 6449 PrintF(out, "stack_slots = %d\n", stack_slots()); |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6708 static_cast<uint32_t> | 6796 static_cast<uint32_t> |
| 6709 (Smi::cast(JSArray::cast(this)->length())->value()) : | 6797 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 6710 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 6798 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 6711 if ((index < length) && | 6799 if ((index < length) && |
| 6712 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 6800 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 6713 return true; | 6801 return true; |
| 6714 } | 6802 } |
| 6715 break; | 6803 break; |
| 6716 } | 6804 } |
| 6717 case PIXEL_ELEMENTS: { | 6805 case PIXEL_ELEMENTS: { |
| 6718 // TODO(iposva): Add testcase. | |
| 6719 PixelArray* pixels = PixelArray::cast(elements()); | 6806 PixelArray* pixels = PixelArray::cast(elements()); |
| 6720 if (index < static_cast<uint32_t>(pixels->length())) { | 6807 if (index < static_cast<uint32_t>(pixels->length())) { |
| 6721 return true; | 6808 return true; |
| 6722 } | 6809 } |
| 6723 break; | 6810 break; |
| 6724 } | 6811 } |
| 6725 case EXTERNAL_BYTE_ELEMENTS: | 6812 case EXTERNAL_BYTE_ELEMENTS: |
| 6726 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 6813 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 6727 case EXTERNAL_SHORT_ELEMENTS: | 6814 case EXTERNAL_SHORT_ELEMENTS: |
| 6728 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 6815 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 6729 case EXTERNAL_INT_ELEMENTS: | 6816 case EXTERNAL_INT_ELEMENTS: |
| 6730 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 6817 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 6731 case EXTERNAL_FLOAT_ELEMENTS: { | 6818 case EXTERNAL_FLOAT_ELEMENTS: { |
| 6732 // TODO(kbr): Add testcase. | |
| 6733 ExternalArray* array = ExternalArray::cast(elements()); | 6819 ExternalArray* array = ExternalArray::cast(elements()); |
| 6734 if (index < static_cast<uint32_t>(array->length())) { | 6820 if (index < static_cast<uint32_t>(array->length())) { |
| 6735 return true; | 6821 return true; |
| 6736 } | 6822 } |
| 6737 break; | 6823 break; |
| 6738 } | 6824 } |
| 6739 case DICTIONARY_ELEMENTS: { | 6825 case DICTIONARY_ELEMENTS: { |
| 6740 if (element_dictionary()->FindEntry(index) | 6826 if (element_dictionary()->FindEntry(index) |
| 6741 != NumberDictionary::kNotFound) { | 6827 != NumberDictionary::kNotFound) { |
| 6742 return true; | 6828 return true; |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7312 { MaybeObject* maybe_len = | 7398 { MaybeObject* maybe_len = |
| 7313 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); | 7399 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); |
| 7314 if (!maybe_len->ToObject(&len)) return maybe_len; | 7400 if (!maybe_len->ToObject(&len)) return maybe_len; |
| 7315 } | 7401 } |
| 7316 set_length(len); | 7402 set_length(len); |
| 7317 } | 7403 } |
| 7318 return value; | 7404 return value; |
| 7319 } | 7405 } |
| 7320 | 7406 |
| 7321 | 7407 |
| 7322 MaybeObject* JSObject::GetElementPostInterceptor(JSObject* receiver, | 7408 MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, |
| 7323 uint32_t index) { | 7409 uint32_t index) { |
| 7324 Heap* heap = GetHeap(); | 7410 Heap* heap = GetHeap(); |
| 7325 // Get element works for both JSObject and JSArray since | 7411 // Get element works for both JSObject and JSArray since |
| 7326 // JSArray::length cannot change. | 7412 // JSArray::length cannot change. |
| 7327 switch (GetElementsKind()) { | 7413 switch (GetElementsKind()) { |
| 7328 case FAST_ELEMENTS: { | 7414 case FAST_ELEMENTS: { |
| 7329 FixedArray* elms = FixedArray::cast(elements()); | 7415 FixedArray* elms = FixedArray::cast(elements()); |
| 7330 if (index < static_cast<uint32_t>(elms->length())) { | 7416 if (index < static_cast<uint32_t>(elms->length())) { |
| 7331 Object* value = elms->get(index); | 7417 Object* value = elms->get(index); |
| 7332 if (!value->IsTheHole()) return value; | 7418 if (!value->IsTheHole()) return value; |
| 7333 } | 7419 } |
| 7334 break; | 7420 break; |
| 7335 } | 7421 } |
| 7336 case PIXEL_ELEMENTS: { | 7422 case PIXEL_ELEMENTS: |
| 7337 // TODO(iposva): Add testcase and implement. | |
| 7338 UNIMPLEMENTED(); | |
| 7339 break; | |
| 7340 } | |
| 7341 case EXTERNAL_BYTE_ELEMENTS: | 7423 case EXTERNAL_BYTE_ELEMENTS: |
| 7342 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 7424 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7343 case EXTERNAL_SHORT_ELEMENTS: | 7425 case EXTERNAL_SHORT_ELEMENTS: |
| 7344 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 7426 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7345 case EXTERNAL_INT_ELEMENTS: | 7427 case EXTERNAL_INT_ELEMENTS: |
| 7346 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 7428 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7347 case EXTERNAL_FLOAT_ELEMENTS: { | 7429 case EXTERNAL_FLOAT_ELEMENTS: { |
| 7348 // TODO(kbr): Add testcase and implement. | 7430 MaybeObject* maybe_value = GetExternalElement(index); |
| 7349 UNIMPLEMENTED(); | 7431 Object* value; |
| 7432 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 7433 if (!value->IsUndefined()) return value; |
| 7350 break; | 7434 break; |
| 7351 } | 7435 } |
| 7352 case DICTIONARY_ELEMENTS: { | 7436 case DICTIONARY_ELEMENTS: { |
| 7353 NumberDictionary* dictionary = element_dictionary(); | 7437 NumberDictionary* dictionary = element_dictionary(); |
| 7354 int entry = dictionary->FindEntry(index); | 7438 int entry = dictionary->FindEntry(index); |
| 7355 if (entry != NumberDictionary::kNotFound) { | 7439 if (entry != NumberDictionary::kNotFound) { |
| 7356 Object* element = dictionary->ValueAt(entry); | 7440 Object* element = dictionary->ValueAt(entry); |
| 7357 PropertyDetails details = dictionary->DetailsAt(entry); | 7441 PropertyDetails details = dictionary->DetailsAt(entry); |
| 7358 if (details.type() == CALLBACKS) { | 7442 if (details.type() == CALLBACKS) { |
| 7359 return GetElementWithCallback(receiver, | 7443 return GetElementWithCallback(receiver, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7370 break; | 7454 break; |
| 7371 } | 7455 } |
| 7372 | 7456 |
| 7373 // Continue searching via the prototype chain. | 7457 // Continue searching via the prototype chain. |
| 7374 Object* pt = GetPrototype(); | 7458 Object* pt = GetPrototype(); |
| 7375 if (pt->IsNull()) return heap->undefined_value(); | 7459 if (pt->IsNull()) return heap->undefined_value(); |
| 7376 return pt->GetElementWithReceiver(receiver, index); | 7460 return pt->GetElementWithReceiver(receiver, index); |
| 7377 } | 7461 } |
| 7378 | 7462 |
| 7379 | 7463 |
| 7380 MaybeObject* JSObject::GetElementWithInterceptor(JSObject* receiver, | 7464 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, |
| 7381 uint32_t index) { | 7465 uint32_t index) { |
| 7382 Isolate* isolate = GetIsolate(); | 7466 Isolate* isolate = GetIsolate(); |
| 7383 // Make sure that the top context does not change when doing | 7467 // Make sure that the top context does not change when doing |
| 7384 // callbacks or interceptor calls. | 7468 // callbacks or interceptor calls. |
| 7385 AssertNoContextChange ncc; | 7469 AssertNoContextChange ncc; |
| 7386 HandleScope scope(isolate); | 7470 HandleScope scope(isolate); |
| 7387 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 7471 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 7388 Handle<JSObject> this_handle(receiver); | 7472 Handle<Object> this_handle(receiver); |
| 7389 Handle<JSObject> holder_handle(this); | 7473 Handle<JSObject> holder_handle(this); |
| 7390 | 7474 |
| 7391 if (!interceptor->getter()->IsUndefined()) { | 7475 if (!interceptor->getter()->IsUndefined()) { |
| 7392 v8::IndexedPropertyGetter getter = | 7476 v8::IndexedPropertyGetter getter = |
| 7393 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 7477 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); |
| 7394 LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); | 7478 LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); |
| 7395 CustomArguments args(isolate, interceptor->data(), receiver, this); | 7479 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 7396 v8::AccessorInfo info(args.end()); | 7480 v8::AccessorInfo info(args.end()); |
| 7397 v8::Handle<v8::Value> result; | 7481 v8::Handle<v8::Value> result; |
| 7398 { | 7482 { |
| 7399 // Leaving JavaScript. | 7483 // Leaving JavaScript. |
| 7400 VMState state(isolate, EXTERNAL); | 7484 VMState state(isolate, EXTERNAL); |
| 7401 result = getter(index, info); | 7485 result = getter(index, info); |
| 7402 } | 7486 } |
| 7403 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 7487 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7404 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); | 7488 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); |
| 7405 } | 7489 } |
| 7406 | 7490 |
| 7407 MaybeObject* raw_result = | 7491 MaybeObject* raw_result = |
| 7408 holder_handle->GetElementPostInterceptor(*this_handle, index); | 7492 holder_handle->GetElementPostInterceptor(*this_handle, index); |
| 7409 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 7493 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7410 return raw_result; | 7494 return raw_result; |
| 7411 } | 7495 } |
| 7412 | 7496 |
| 7413 | 7497 |
| 7414 MaybeObject* JSObject::GetElementWithReceiver(JSObject* receiver, | 7498 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, |
| 7415 uint32_t index) { | 7499 uint32_t index) { |
| 7416 Heap* heap = GetHeap(); | 7500 Heap* heap = GetHeap(); |
| 7417 // Check access rights if needed. | 7501 // Check access rights if needed. |
| 7418 if (IsAccessCheckNeeded() && | 7502 if (IsAccessCheckNeeded() && |
| 7419 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { | 7503 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { |
| 7420 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); | 7504 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 7421 return heap->undefined_value(); | 7505 return heap->undefined_value(); |
| 7422 } | 7506 } |
| 7423 | 7507 |
| 7424 if (HasIndexedInterceptor()) { | 7508 if (HasIndexedInterceptor()) { |
| 7425 return GetElementWithInterceptor(receiver, index); | 7509 return GetElementWithInterceptor(receiver, index); |
| 7426 } | 7510 } |
| 7427 | 7511 |
| 7428 // Get element works for both JSObject and JSArray since | 7512 // Get element works for both JSObject and JSArray since |
| 7429 // JSArray::length cannot change. | 7513 // JSArray::length cannot change. |
| 7430 switch (GetElementsKind()) { | 7514 switch (GetElementsKind()) { |
| 7431 case FAST_ELEMENTS: { | 7515 case FAST_ELEMENTS: { |
| 7432 FixedArray* elms = FixedArray::cast(elements()); | 7516 FixedArray* elms = FixedArray::cast(elements()); |
| 7433 if (index < static_cast<uint32_t>(elms->length())) { | 7517 if (index < static_cast<uint32_t>(elms->length())) { |
| 7434 Object* value = elms->get(index); | 7518 Object* value = elms->get(index); |
| 7435 if (!value->IsTheHole()) return value; | 7519 if (!value->IsTheHole()) return value; |
| 7436 } | 7520 } |
| 7437 break; | 7521 break; |
| 7438 } | 7522 } |
| 7523 case PIXEL_ELEMENTS: |
| 7524 case EXTERNAL_BYTE_ELEMENTS: |
| 7525 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7526 case EXTERNAL_SHORT_ELEMENTS: |
| 7527 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7528 case EXTERNAL_INT_ELEMENTS: |
| 7529 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7530 case EXTERNAL_FLOAT_ELEMENTS: { |
| 7531 MaybeObject* maybe_value = GetExternalElement(index); |
| 7532 Object* value; |
| 7533 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 7534 if (!value->IsUndefined()) return value; |
| 7535 break; |
| 7536 } |
| 7537 case DICTIONARY_ELEMENTS: { |
| 7538 NumberDictionary* dictionary = element_dictionary(); |
| 7539 int entry = dictionary->FindEntry(index); |
| 7540 if (entry != NumberDictionary::kNotFound) { |
| 7541 Object* element = dictionary->ValueAt(entry); |
| 7542 PropertyDetails details = dictionary->DetailsAt(entry); |
| 7543 if (details.type() == CALLBACKS) { |
| 7544 return GetElementWithCallback(receiver, |
| 7545 element, |
| 7546 index, |
| 7547 this); |
| 7548 } |
| 7549 return element; |
| 7550 } |
| 7551 break; |
| 7552 } |
| 7553 } |
| 7554 |
| 7555 Object* pt = GetPrototype(); |
| 7556 if (pt == heap->null_value()) return heap->undefined_value(); |
| 7557 return pt->GetElementWithReceiver(receiver, index); |
| 7558 } |
| 7559 |
| 7560 |
| 7561 MaybeObject* JSObject::GetExternalElement(uint32_t index) { |
| 7562 // Get element works for both JSObject and JSArray since |
| 7563 // JSArray::length cannot change. |
| 7564 switch (GetElementsKind()) { |
| 7439 case PIXEL_ELEMENTS: { | 7565 case PIXEL_ELEMENTS: { |
| 7440 PixelArray* pixels = PixelArray::cast(elements()); | 7566 PixelArray* pixels = PixelArray::cast(elements()); |
| 7441 if (index < static_cast<uint32_t>(pixels->length())) { | 7567 if (index < static_cast<uint32_t>(pixels->length())) { |
| 7442 uint8_t value = pixels->get(index); | 7568 uint8_t value = pixels->get(index); |
| 7443 return Smi::FromInt(value); | 7569 return Smi::FromInt(value); |
| 7444 } | 7570 } |
| 7445 break; | 7571 break; |
| 7446 } | 7572 } |
| 7447 case EXTERNAL_BYTE_ELEMENTS: { | 7573 case EXTERNAL_BYTE_ELEMENTS: { |
| 7448 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 7574 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 7475 if (index < static_cast<uint32_t>(array->length())) { | 7601 if (index < static_cast<uint32_t>(array->length())) { |
| 7476 uint16_t value = array->get(index); | 7602 uint16_t value = array->get(index); |
| 7477 return Smi::FromInt(value); | 7603 return Smi::FromInt(value); |
| 7478 } | 7604 } |
| 7479 break; | 7605 break; |
| 7480 } | 7606 } |
| 7481 case EXTERNAL_INT_ELEMENTS: { | 7607 case EXTERNAL_INT_ELEMENTS: { |
| 7482 ExternalIntArray* array = ExternalIntArray::cast(elements()); | 7608 ExternalIntArray* array = ExternalIntArray::cast(elements()); |
| 7483 if (index < static_cast<uint32_t>(array->length())) { | 7609 if (index < static_cast<uint32_t>(array->length())) { |
| 7484 int32_t value = array->get(index); | 7610 int32_t value = array->get(index); |
| 7485 return heap->NumberFromInt32(value); | 7611 return GetHeap()->NumberFromInt32(value); |
| 7486 } | 7612 } |
| 7487 break; | 7613 break; |
| 7488 } | 7614 } |
| 7489 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | 7615 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 7490 ExternalUnsignedIntArray* array = | 7616 ExternalUnsignedIntArray* array = |
| 7491 ExternalUnsignedIntArray::cast(elements()); | 7617 ExternalUnsignedIntArray::cast(elements()); |
| 7492 if (index < static_cast<uint32_t>(array->length())) { | 7618 if (index < static_cast<uint32_t>(array->length())) { |
| 7493 uint32_t value = array->get(index); | 7619 uint32_t value = array->get(index); |
| 7494 return heap->NumberFromUint32(value); | 7620 return GetHeap()->NumberFromUint32(value); |
| 7495 } | 7621 } |
| 7496 break; | 7622 break; |
| 7497 } | 7623 } |
| 7498 case EXTERNAL_FLOAT_ELEMENTS: { | 7624 case EXTERNAL_FLOAT_ELEMENTS: { |
| 7499 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); | 7625 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); |
| 7500 if (index < static_cast<uint32_t>(array->length())) { | 7626 if (index < static_cast<uint32_t>(array->length())) { |
| 7501 float value = array->get(index); | 7627 float value = array->get(index); |
| 7502 return heap->AllocateHeapNumber(value); | 7628 return GetHeap()->AllocateHeapNumber(value); |
| 7503 } | 7629 } |
| 7504 break; | 7630 break; |
| 7505 } | 7631 } |
| 7506 case DICTIONARY_ELEMENTS: { | 7632 case FAST_ELEMENTS: |
| 7507 NumberDictionary* dictionary = element_dictionary(); | 7633 case DICTIONARY_ELEMENTS: |
| 7508 int entry = dictionary->FindEntry(index); | 7634 UNREACHABLE(); |
| 7509 if (entry != NumberDictionary::kNotFound) { | |
| 7510 Object* element = dictionary->ValueAt(entry); | |
| 7511 PropertyDetails details = dictionary->DetailsAt(entry); | |
| 7512 if (details.type() == CALLBACKS) { | |
| 7513 return GetElementWithCallback(receiver, | |
| 7514 element, | |
| 7515 index, | |
| 7516 this); | |
| 7517 } | |
| 7518 return element; | |
| 7519 } | |
| 7520 break; | 7635 break; |
| 7521 } | |
| 7522 } | 7636 } |
| 7523 | 7637 return GetHeap()->undefined_value(); |
| 7524 Object* pt = GetPrototype(); | |
| 7525 if (pt->IsNull()) return heap->undefined_value(); | |
| 7526 return pt->GetElementWithReceiver(receiver, index); | |
| 7527 } | 7638 } |
| 7528 | 7639 |
| 7529 | 7640 |
| 7530 bool JSObject::HasDenseElements() { | 7641 bool JSObject::HasDenseElements() { |
| 7531 int capacity = 0; | 7642 int capacity = 0; |
| 7532 int number_of_elements = 0; | 7643 int number_of_elements = 0; |
| 7533 | 7644 |
| 7534 switch (GetElementsKind()) { | 7645 switch (GetElementsKind()) { |
| 7535 case FAST_ELEMENTS: { | 7646 case FAST_ELEMENTS: { |
| 7536 FixedArray* elms = FixedArray::cast(elements()); | 7647 FixedArray* elms = FixedArray::cast(elements()); |
| (...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8634 return Smi::FromInt(-1); | 8745 return Smi::FromInt(-1); |
| 8635 } | 8746 } |
| 8636 uint32_t key = NumberToUint32(k); | 8747 uint32_t key = NumberToUint32(k); |
| 8637 // In the following we assert that adding the entry to the new dictionary | 8748 // In the following we assert that adding the entry to the new dictionary |
| 8638 // does not cause GC. This is the case because we made sure to allocate | 8749 // does not cause GC. This is the case because we made sure to allocate |
| 8639 // the dictionary big enough above, so it need not grow. | 8750 // the dictionary big enough above, so it need not grow. |
| 8640 if (key < limit) { | 8751 if (key < limit) { |
| 8641 if (value->IsUndefined()) { | 8752 if (value->IsUndefined()) { |
| 8642 undefs++; | 8753 undefs++; |
| 8643 } else { | 8754 } else { |
| 8755 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8756 // Adding an entry with the key beyond smi-range requires |
| 8757 // allocation. Bailout. |
| 8758 return Smi::FromInt(-1); |
| 8759 } |
| 8644 new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked(); | 8760 new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked(); |
| 8645 pos++; | 8761 pos++; |
| 8646 } | 8762 } |
| 8647 } else { | 8763 } else { |
| 8764 if (key > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8765 // Adding an entry with the key beyond smi-range requires |
| 8766 // allocation. Bailout. |
| 8767 return Smi::FromInt(-1); |
| 8768 } |
| 8648 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); | 8769 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); |
| 8649 } | 8770 } |
| 8650 } | 8771 } |
| 8651 } | 8772 } |
| 8652 | 8773 |
| 8653 uint32_t result = pos; | 8774 uint32_t result = pos; |
| 8654 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); | 8775 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); |
| 8655 while (undefs > 0) { | 8776 while (undefs > 0) { |
| 8777 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8778 // Adding an entry with the key beyond smi-range requires |
| 8779 // allocation. Bailout. |
| 8780 return Smi::FromInt(-1); |
| 8781 } |
| 8656 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)-> | 8782 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)-> |
| 8657 ToObjectUnchecked(); | 8783 ToObjectUnchecked(); |
| 8658 pos++; | 8784 pos++; |
| 8659 undefs--; | 8785 undefs--; |
| 8660 } | 8786 } |
| 8661 | 8787 |
| 8662 set_elements(new_dict); | 8788 set_elements(new_dict); |
| 8663 | 8789 |
| 8664 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 8790 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8665 return Smi::FromInt(static_cast<int>(result)); | 8791 return Smi::FromInt(static_cast<int>(result)); |
| (...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9386 ElementsRemoved(removed_entries); | 9512 ElementsRemoved(removed_entries); |
| 9387 } | 9513 } |
| 9388 | 9514 |
| 9389 | 9515 |
| 9390 template<typename Shape, typename Key> | 9516 template<typename Shape, typename Key> |
| 9391 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, | 9517 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| 9392 JSObject::DeleteMode mode) { | 9518 JSObject::DeleteMode mode) { |
| 9393 Heap* heap = Dictionary<Shape, Key>::GetHeap(); | 9519 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 9394 PropertyDetails details = DetailsAt(entry); | 9520 PropertyDetails details = DetailsAt(entry); |
| 9395 // Ignore attributes if forcing a deletion. | 9521 // Ignore attributes if forcing a deletion. |
| 9396 if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) { | 9522 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { |
| 9397 return heap->false_value(); | 9523 return heap->false_value(); |
| 9398 } | 9524 } |
| 9399 SetEntry(entry, heap->null_value(), heap->null_value(), Smi::FromInt(0)); | 9525 SetEntry(entry, heap->null_value(), heap->null_value(), Smi::FromInt(0)); |
| 9400 HashTable<Shape, Key>::ElementRemoved(); | 9526 HashTable<Shape, Key>::ElementRemoved(); |
| 9401 return heap->true_value(); | 9527 return heap->true_value(); |
| 9402 } | 9528 } |
| 9403 | 9529 |
| 9404 | 9530 |
| 9405 template<typename Shape, typename Key> | 9531 template<typename Shape, typename Key> |
| 9406 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { | 9532 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10011 if (break_point_objects()->IsUndefined()) return 0; | 10137 if (break_point_objects()->IsUndefined()) return 0; |
| 10012 // Single beak point. | 10138 // Single beak point. |
| 10013 if (!break_point_objects()->IsFixedArray()) return 1; | 10139 if (!break_point_objects()->IsFixedArray()) return 1; |
| 10014 // Multiple break points. | 10140 // Multiple break points. |
| 10015 return FixedArray::cast(break_point_objects())->length(); | 10141 return FixedArray::cast(break_point_objects())->length(); |
| 10016 } | 10142 } |
| 10017 #endif | 10143 #endif |
| 10018 | 10144 |
| 10019 | 10145 |
| 10020 } } // namespace v8::internal | 10146 } } // namespace v8::internal |
| OLD | NEW |