| 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 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 accumulator->Add("<ExternalUnsignedIntArray[%u]>", | 995 accumulator->Add("<ExternalUnsignedIntArray[%u]>", |
| 996 ExternalUnsignedIntArray::cast(this)->length()); | 996 ExternalUnsignedIntArray::cast(this)->length()); |
| 997 break; | 997 break; |
| 998 case EXTERNAL_FLOAT_ARRAY_TYPE: | 998 case EXTERNAL_FLOAT_ARRAY_TYPE: |
| 999 accumulator->Add("<ExternalFloatArray[%u]>", | 999 accumulator->Add("<ExternalFloatArray[%u]>", |
| 1000 ExternalFloatArray::cast(this)->length()); | 1000 ExternalFloatArray::cast(this)->length()); |
| 1001 break; | 1001 break; |
| 1002 case SHARED_FUNCTION_INFO_TYPE: | 1002 case SHARED_FUNCTION_INFO_TYPE: |
| 1003 accumulator->Add("<SharedFunctionInfo>"); | 1003 accumulator->Add("<SharedFunctionInfo>"); |
| 1004 break; | 1004 break; |
| 1005 case JS_MESSAGE_OBJECT_TYPE: |
| 1006 accumulator->Add("<JSMessageObject>"); |
| 1007 break; |
| 1005 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 1008 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
| 1006 case NAME##_TYPE: \ | 1009 case NAME##_TYPE: \ |
| 1007 accumulator->Put('<'); \ | 1010 accumulator->Put('<'); \ |
| 1008 accumulator->Add(#Name); \ | 1011 accumulator->Add(#Name); \ |
| 1009 accumulator->Put('>'); \ | 1012 accumulator->Put('>'); \ |
| 1010 break; | 1013 break; |
| 1011 STRUCT_LIST(MAKE_STRUCT_CASE) | 1014 STRUCT_LIST(MAKE_STRUCT_CASE) |
| 1012 #undef MAKE_STRUCT_CASE | 1015 #undef MAKE_STRUCT_CASE |
| 1013 case CODE_TYPE: | 1016 case CODE_TYPE: |
| 1014 accumulator->Add("<Code>"); | 1017 accumulator->Add("<Code>"); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); | 1088 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); |
| 1086 break; | 1089 break; |
| 1087 case JS_OBJECT_TYPE: | 1090 case JS_OBJECT_TYPE: |
| 1088 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 1091 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 1089 case JS_VALUE_TYPE: | 1092 case JS_VALUE_TYPE: |
| 1090 case JS_ARRAY_TYPE: | 1093 case JS_ARRAY_TYPE: |
| 1091 case JS_REGEXP_TYPE: | 1094 case JS_REGEXP_TYPE: |
| 1092 case JS_GLOBAL_PROXY_TYPE: | 1095 case JS_GLOBAL_PROXY_TYPE: |
| 1093 case JS_GLOBAL_OBJECT_TYPE: | 1096 case JS_GLOBAL_OBJECT_TYPE: |
| 1094 case JS_BUILTINS_OBJECT_TYPE: | 1097 case JS_BUILTINS_OBJECT_TYPE: |
| 1098 case JS_MESSAGE_OBJECT_TYPE: |
| 1095 JSObject::BodyDescriptor::IterateBody(this, object_size, v); | 1099 JSObject::BodyDescriptor::IterateBody(this, object_size, v); |
| 1096 break; | 1100 break; |
| 1097 case JS_FUNCTION_TYPE: | 1101 case JS_FUNCTION_TYPE: |
| 1098 reinterpret_cast<JSFunction*>(this) | 1102 reinterpret_cast<JSFunction*>(this) |
| 1099 ->JSFunctionIterateBody(object_size, v); | 1103 ->JSFunctionIterateBody(object_size, v); |
| 1100 break; | 1104 break; |
| 1101 case ODDBALL_TYPE: | 1105 case ODDBALL_TYPE: |
| 1102 Oddball::BodyDescriptor::IterateBody(this, v); | 1106 Oddball::BodyDescriptor::IterateBody(this, v); |
| 1103 break; | 1107 break; |
| 1104 case PROXY_TYPE: | 1108 case PROXY_TYPE: |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1225 set_properties(FixedArray::cast(values)); | 1229 set_properties(FixedArray::cast(values)); |
| 1226 } | 1230 } |
| 1227 set_map(new_map); | 1231 set_map(new_map); |
| 1228 return FastPropertyAtPut(index, value); | 1232 return FastPropertyAtPut(index, value); |
| 1229 } | 1233 } |
| 1230 | 1234 |
| 1231 | 1235 |
| 1232 MaybeObject* JSObject::AddFastProperty(String* name, | 1236 MaybeObject* JSObject::AddFastProperty(String* name, |
| 1233 Object* value, | 1237 Object* value, |
| 1234 PropertyAttributes attributes) { | 1238 PropertyAttributes attributes) { |
| 1239 ASSERT(!IsJSGlobalProxy()); |
| 1240 |
| 1235 // Normalize the object if the name is an actual string (not the | 1241 // Normalize the object if the name is an actual string (not the |
| 1236 // hidden symbols) and is not a real identifier. | 1242 // hidden symbols) and is not a real identifier. |
| 1237 Isolate* isolate = GetHeap()->isolate(); | 1243 Isolate* isolate = GetHeap()->isolate(); |
| 1238 StringInputBuffer buffer(name); | 1244 StringInputBuffer buffer(name); |
| 1239 if (!isolate->scanner_constants()->IsIdentifier(&buffer) | 1245 if (!isolate->scanner_constants()->IsIdentifier(&buffer) |
| 1240 && name != HEAP->hidden_symbol()) { | 1246 && name != HEAP->hidden_symbol()) { |
| 1241 Object* obj; | 1247 Object* obj; |
| 1242 { MaybeObject* maybe_obj = | 1248 { MaybeObject* maybe_obj = |
| 1243 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1249 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 1244 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1250 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1731 } | 1737 } |
| 1732 if (result->type() == CALLBACKS) { | 1738 if (result->type() == CALLBACKS) { |
| 1733 return; | 1739 return; |
| 1734 } | 1740 } |
| 1735 } | 1741 } |
| 1736 } | 1742 } |
| 1737 result->NotFound(); | 1743 result->NotFound(); |
| 1738 } | 1744 } |
| 1739 | 1745 |
| 1740 | 1746 |
| 1741 bool JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, | 1747 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, |
| 1742 Object* value) { | 1748 Object* value, |
| 1749 bool* found) { |
| 1743 Heap* heap = GetHeap(); | 1750 Heap* heap = GetHeap(); |
| 1744 for (Object* pt = GetPrototype(); | 1751 for (Object* pt = GetPrototype(); |
| 1745 pt != heap->null_value(); | 1752 pt != heap->null_value(); |
| 1746 pt = pt->GetPrototype()) { | 1753 pt = pt->GetPrototype()) { |
| 1747 if (!JSObject::cast(pt)->HasDictionaryElements()) { | 1754 if (!JSObject::cast(pt)->HasDictionaryElements()) { |
| 1748 continue; | 1755 continue; |
| 1749 } | 1756 } |
| 1750 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); | 1757 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| 1751 int entry = dictionary->FindEntry(index); | 1758 int entry = dictionary->FindEntry(index); |
| 1752 if (entry != NumberDictionary::kNotFound) { | 1759 if (entry != NumberDictionary::kNotFound) { |
| 1753 Object* element = dictionary->ValueAt(entry); | |
| 1754 PropertyDetails details = dictionary->DetailsAt(entry); | 1760 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1755 if (details.type() == CALLBACKS) { | 1761 if (details.type() == CALLBACKS) { |
| 1756 SetElementWithCallback(element, index, value, JSObject::cast(pt)); | 1762 *found = true; |
| 1757 return true; | 1763 return SetElementWithCallback( |
| 1764 dictionary->ValueAt(entry), index, value, JSObject::cast(pt)); |
| 1758 } | 1765 } |
| 1759 } | 1766 } |
| 1760 } | 1767 } |
| 1761 return false; | 1768 *found = false; |
| 1769 return heap->the_hole_value(); |
| 1762 } | 1770 } |
| 1763 | 1771 |
| 1764 | 1772 |
| 1765 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { | 1773 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { |
| 1766 DescriptorArray* descriptors = map()->instance_descriptors(); | 1774 DescriptorArray* descriptors = map()->instance_descriptors(); |
| 1767 int number = descriptors->SearchWithCache(name); | 1775 int number = descriptors->SearchWithCache(name); |
| 1768 if (number != DescriptorArray::kNotFound) { | 1776 if (number != DescriptorArray::kNotFound) { |
| 1769 result->DescriptorResult(this, descriptors->GetDetails(number), number); | 1777 result->DescriptorResult(this, descriptors->GetDetails(number), number); |
| 1770 } else { | 1778 } else { |
| 1771 result->NotFound(); | 1779 result->NotFound(); |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2323 return map()->UpdateCodeCache(name, code); | 2331 return map()->UpdateCodeCache(name, code); |
| 2324 } | 2332 } |
| 2325 | 2333 |
| 2326 | 2334 |
| 2327 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, | 2335 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, |
| 2328 int expected_additional_properties) { | 2336 int expected_additional_properties) { |
| 2329 if (!HasFastProperties()) return this; | 2337 if (!HasFastProperties()) return this; |
| 2330 | 2338 |
| 2331 // The global object is always normalized. | 2339 // The global object is always normalized. |
| 2332 ASSERT(!IsGlobalObject()); | 2340 ASSERT(!IsGlobalObject()); |
| 2341 // JSGlobalProxy must never be normalized |
| 2342 ASSERT(!IsJSGlobalProxy()); |
| 2333 | 2343 |
| 2334 Heap* heap = GetHeap(); | 2344 Heap* heap = GetHeap(); |
| 2335 | 2345 |
| 2336 // Allocate new content. | 2346 // Allocate new content. |
| 2337 int property_count = map()->NumberOfDescribedProperties(); | 2347 int property_count = map()->NumberOfDescribedProperties(); |
| 2338 if (expected_additional_properties > 0) { | 2348 if (expected_additional_properties > 0) { |
| 2339 property_count += expected_additional_properties; | 2349 property_count += expected_additional_properties; |
| 2340 } else { | 2350 } else { |
| 2341 property_count += 2; // Make space for two more properties. | 2351 property_count += 2; // Make space for two more properties. |
| 2342 } | 2352 } |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2823 return context->extension()->ReferencesObject(obj); | 2833 return context->extension()->ReferencesObject(obj); |
| 2824 } | 2834 } |
| 2825 } | 2835 } |
| 2826 | 2836 |
| 2827 // No references to object. | 2837 // No references to object. |
| 2828 return false; | 2838 return false; |
| 2829 } | 2839 } |
| 2830 | 2840 |
| 2831 | 2841 |
| 2832 MaybeObject* JSObject::PreventExtensions() { | 2842 MaybeObject* JSObject::PreventExtensions() { |
| 2843 if (IsJSGlobalProxy()) { |
| 2844 Object* proto = GetPrototype(); |
| 2845 if (proto->IsNull()) return this; |
| 2846 ASSERT(proto->IsJSGlobalObject()); |
| 2847 return JSObject::cast(proto)->PreventExtensions(); |
| 2848 } |
| 2849 |
| 2833 // If there are fast elements we normalize. | 2850 // If there are fast elements we normalize. |
| 2834 if (HasFastElements()) { | 2851 if (HasFastElements()) { |
| 2835 Object* ok; | 2852 Object* ok; |
| 2836 { MaybeObject* maybe_ok = NormalizeElements(); | 2853 { MaybeObject* maybe_ok = NormalizeElements(); |
| 2837 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 2854 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 2838 } | 2855 } |
| 2839 } | 2856 } |
| 2840 // Make sure that we never go back to fast case. | 2857 // Make sure that we never go back to fast case. |
| 2841 element_dictionary()->set_requires_slow_elements(); | 2858 element_dictionary()->set_requires_slow_elements(); |
| 2842 | 2859 |
| (...skipping 3174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6017 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 6034 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
| 6018 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | 6035 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
| 6019 RelocInfo::kApplyMask; | 6036 RelocInfo::kApplyMask; |
| 6020 Assembler* origin = desc.origin; // Needed to find target_object on X64. | 6037 Assembler* origin = desc.origin; // Needed to find target_object on X64. |
| 6021 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { | 6038 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { |
| 6022 RelocInfo::Mode mode = it.rinfo()->rmode(); | 6039 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 6023 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 6040 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| 6024 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 6041 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 6025 it.rinfo()->set_target_object(*p); | 6042 it.rinfo()->set_target_object(*p); |
| 6026 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { | 6043 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { |
| 6027 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); | 6044 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); |
| 6028 it.rinfo()->set_target_cell(*cell); | 6045 it.rinfo()->set_target_cell(*cell); |
| 6029 } else if (RelocInfo::IsCodeTarget(mode)) { | 6046 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 6030 // rewrite code handles in inline cache targets to direct | 6047 // rewrite code handles in inline cache targets to direct |
| 6031 // pointers to the first instruction in the code object | 6048 // pointers to the first instruction in the code object |
| 6032 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 6049 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 6033 Code* code = Code::cast(*p); | 6050 Code* code = Code::cast(*p); |
| 6034 it.rinfo()->set_target_address(code->instruction_start()); | 6051 it.rinfo()->set_target_address(code->instruction_start()); |
| 6035 } else { | 6052 } else { |
| 6036 it.rinfo()->apply(delta); | 6053 it.rinfo()->apply(delta); |
| 6037 } | 6054 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6098 | 6115 |
| 6099 SafepointEntry Code::GetSafepointEntry(Address pc) { | 6116 SafepointEntry Code::GetSafepointEntry(Address pc) { |
| 6100 SafepointTable table(this); | 6117 SafepointTable table(this); |
| 6101 return table.FindEntry(pc); | 6118 return table.FindEntry(pc); |
| 6102 } | 6119 } |
| 6103 | 6120 |
| 6104 | 6121 |
| 6105 void Code::SetNoStackCheckTable() { | 6122 void Code::SetNoStackCheckTable() { |
| 6106 // Indicate the absence of a stack-check table by a table start after the | 6123 // Indicate the absence of a stack-check table by a table start after the |
| 6107 // end of the instructions. Table start must be aligned, so round up. | 6124 // end of the instructions. Table start must be aligned, so round up. |
| 6108 set_stack_check_table_start(RoundUp(instruction_size(), kIntSize)); | 6125 set_stack_check_table_offset(RoundUp(instruction_size(), kIntSize)); |
| 6109 } | 6126 } |
| 6110 | 6127 |
| 6111 | 6128 |
| 6112 Map* Code::FindFirstMap() { | 6129 Map* Code::FindFirstMap() { |
| 6113 ASSERT(is_inline_cache_stub()); | 6130 ASSERT(is_inline_cache_stub()); |
| 6114 AssertNoAllocation no_allocation; | 6131 AssertNoAllocation no_allocation; |
| 6115 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 6132 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 6116 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 6133 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 6117 RelocInfo* info = it.rinfo(); | 6134 RelocInfo* info = it.rinfo(); |
| 6118 Object* object = info->target_object(); | 6135 Object* object = info->target_object(); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6375 } else { | 6392 } else { |
| 6376 PrintF(out, " <none>"); | 6393 PrintF(out, " <none>"); |
| 6377 } | 6394 } |
| 6378 if (entry.argument_count() > 0) { | 6395 if (entry.argument_count() > 0) { |
| 6379 PrintF(out, " argc: %d", entry.argument_count()); | 6396 PrintF(out, " argc: %d", entry.argument_count()); |
| 6380 } | 6397 } |
| 6381 PrintF(out, "\n"); | 6398 PrintF(out, "\n"); |
| 6382 } | 6399 } |
| 6383 PrintF(out, "\n"); | 6400 PrintF(out, "\n"); |
| 6384 } else if (kind() == FUNCTION) { | 6401 } else if (kind() == FUNCTION) { |
| 6385 unsigned offset = stack_check_table_start(); | 6402 unsigned offset = stack_check_table_offset(); |
| 6386 // If there is no stack check table, the "table start" will at or after | 6403 // If there is no stack check table, the "table start" will at or after |
| 6387 // (due to alignment) the end of the instruction stream. | 6404 // (due to alignment) the end of the instruction stream. |
| 6388 if (static_cast<int>(offset) < instruction_size()) { | 6405 if (static_cast<int>(offset) < instruction_size()) { |
| 6389 unsigned* address = | 6406 unsigned* address = |
| 6390 reinterpret_cast<unsigned*>(instruction_start() + offset); | 6407 reinterpret_cast<unsigned*>(instruction_start() + offset); |
| 6391 unsigned length = address[0]; | 6408 unsigned length = address[0]; |
| 6392 PrintF(out, "Stack checks (size = %u)\n", length); | 6409 PrintF(out, "Stack checks (size = %u)\n", length); |
| 6393 PrintF(out, "ast_id pc_offset\n"); | 6410 PrintF(out, "ast_id pc_offset\n"); |
| 6394 for (unsigned i = 0; i < length; ++i) { | 6411 for (unsigned i = 0; i < length; ++i) { |
| 6395 unsigned index = (2 * i) + 1; | 6412 unsigned index = (2 * i) + 1; |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6784 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { | 6801 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { |
| 6785 Heap* heap = GetHeap(); | 6802 Heap* heap = GetHeap(); |
| 6786 | 6803 |
| 6787 // Check access rights if needed. | 6804 // Check access rights if needed. |
| 6788 if (IsAccessCheckNeeded() && | 6805 if (IsAccessCheckNeeded() && |
| 6789 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6806 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 6790 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6807 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6791 return UNDEFINED_ELEMENT; | 6808 return UNDEFINED_ELEMENT; |
| 6792 } | 6809 } |
| 6793 | 6810 |
| 6811 if (IsJSGlobalProxy()) { |
| 6812 Object* proto = GetPrototype(); |
| 6813 if (proto->IsNull()) return UNDEFINED_ELEMENT; |
| 6814 ASSERT(proto->IsJSGlobalObject()); |
| 6815 return JSObject::cast(proto)->HasLocalElement(index); |
| 6816 } |
| 6817 |
| 6794 // Check for lookup interceptor | 6818 // Check for lookup interceptor |
| 6795 if (HasIndexedInterceptor()) { | 6819 if (HasIndexedInterceptor()) { |
| 6796 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 6820 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
| 6797 : UNDEFINED_ELEMENT; | 6821 : UNDEFINED_ELEMENT; |
| 6798 } | 6822 } |
| 6799 | 6823 |
| 6800 // Handle [] on String objects. | 6824 // Handle [] on String objects. |
| 6801 if (this->IsStringObjectWithCharacterAt(index)) { | 6825 if (this->IsStringObjectWithCharacterAt(index)) { |
| 6802 return STRING_CHARACTER_ELEMENT; | 6826 return STRING_CHARACTER_ELEMENT; |
| 6803 } | 6827 } |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7061 ASSERT(HasFastElements()); | 7085 ASSERT(HasFastElements()); |
| 7062 | 7086 |
| 7063 Object* elms_obj; | 7087 Object* elms_obj; |
| 7064 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); | 7088 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); |
| 7065 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; | 7089 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
| 7066 } | 7090 } |
| 7067 FixedArray* elms = FixedArray::cast(elms_obj); | 7091 FixedArray* elms = FixedArray::cast(elms_obj); |
| 7068 uint32_t elms_length = static_cast<uint32_t>(elms->length()); | 7092 uint32_t elms_length = static_cast<uint32_t>(elms->length()); |
| 7069 | 7093 |
| 7070 if (check_prototype && | 7094 if (check_prototype && |
| 7071 (index >= elms_length || elms->get(index)->IsTheHole()) && | 7095 (index >= elms_length || elms->get(index)->IsTheHole())) { |
| 7072 SetElementWithCallbackSetterInPrototypes(index, value)) { | 7096 bool found; |
| 7073 return value; | 7097 MaybeObject* result = |
| 7098 SetElementWithCallbackSetterInPrototypes(index, value, &found); |
| 7099 if (found) return result; |
| 7074 } | 7100 } |
| 7075 | 7101 |
| 7076 | 7102 |
| 7077 // Check whether there is extra space in fixed array.. | 7103 // Check whether there is extra space in fixed array.. |
| 7078 if (index < elms_length) { | 7104 if (index < elms_length) { |
| 7079 elms->set(index, value); | 7105 elms->set(index, value); |
| 7080 if (IsJSArray()) { | 7106 if (IsJSArray()) { |
| 7081 // Update the length of the array if needed. | 7107 // Update the length of the array if needed. |
| 7082 uint32_t array_length = 0; | 7108 uint32_t array_length = 0; |
| 7083 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 7109 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7197 Object* element = dictionary->ValueAt(entry); | 7223 Object* element = dictionary->ValueAt(entry); |
| 7198 PropertyDetails details = dictionary->DetailsAt(entry); | 7224 PropertyDetails details = dictionary->DetailsAt(entry); |
| 7199 if (details.type() == CALLBACKS) { | 7225 if (details.type() == CALLBACKS) { |
| 7200 return SetElementWithCallback(element, index, value, this); | 7226 return SetElementWithCallback(element, index, value, this); |
| 7201 } else { | 7227 } else { |
| 7202 dictionary->UpdateMaxNumberKey(index); | 7228 dictionary->UpdateMaxNumberKey(index); |
| 7203 dictionary->ValueAtPut(entry, value); | 7229 dictionary->ValueAtPut(entry, value); |
| 7204 } | 7230 } |
| 7205 } else { | 7231 } else { |
| 7206 // Index not already used. Look for an accessor in the prototype chain. | 7232 // Index not already used. Look for an accessor in the prototype chain. |
| 7207 if (check_prototype && | 7233 if (check_prototype) { |
| 7208 SetElementWithCallbackSetterInPrototypes(index, value)) { | 7234 bool found; |
| 7209 return value; | 7235 MaybeObject* result = |
| 7236 SetElementWithCallbackSetterInPrototypes(index, value, &found); |
| 7237 if (found) return result; |
| 7210 } | 7238 } |
| 7211 // When we set the is_extensible flag to false we always force | 7239 // When we set the is_extensible flag to false we always force |
| 7212 // the element into dictionary mode (and force them to stay there). | 7240 // the element into dictionary mode (and force them to stay there). |
| 7213 if (!map()->is_extensible()) { | 7241 if (!map()->is_extensible()) { |
| 7214 Handle<Object> number(FACTORY->NewNumberFromUint(index)); | 7242 Handle<Object> number(FACTORY->NewNumberFromUint(index)); |
| 7215 Handle<String> index_string(FACTORY->NumberToString(number)); | 7243 Handle<String> index_string(FACTORY->NumberToString(number)); |
| 7216 Handle<Object> args[1] = { index_string }; | 7244 Handle<Object> args[1] = { index_string }; |
| 7217 return heap->isolate()->Throw( | 7245 return heap->isolate()->Throw( |
| 7218 *FACTORY->NewTypeError("object_not_extensible", | 7246 *FACTORY->NewTypeError("object_not_extensible", |
| 7219 HandleVector(args, 1))); | 7247 HandleVector(args, 1))); |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8064 Object* AsObject() { return string_; } | 8092 Object* AsObject() { return string_; } |
| 8065 | 8093 |
| 8066 String* string_; | 8094 String* string_; |
| 8067 uint32_t hash_; | 8095 uint32_t hash_; |
| 8068 }; | 8096 }; |
| 8069 | 8097 |
| 8070 | 8098 |
| 8071 // StringSharedKeys are used as keys in the eval cache. | 8099 // StringSharedKeys are used as keys in the eval cache. |
| 8072 class StringSharedKey : public HashTableKey { | 8100 class StringSharedKey : public HashTableKey { |
| 8073 public: | 8101 public: |
| 8074 StringSharedKey(String* source, SharedFunctionInfo* shared) | 8102 StringSharedKey(String* source, |
| 8075 : source_(source), shared_(shared) { } | 8103 SharedFunctionInfo* shared, |
| 8104 StrictModeFlag strict_mode) |
| 8105 : source_(source), |
| 8106 shared_(shared), |
| 8107 strict_mode_(strict_mode) { } |
| 8076 | 8108 |
| 8077 bool IsMatch(Object* other) { | 8109 bool IsMatch(Object* other) { |
| 8078 if (!other->IsFixedArray()) return false; | 8110 if (!other->IsFixedArray()) return false; |
| 8079 FixedArray* pair = FixedArray::cast(other); | 8111 FixedArray* pair = FixedArray::cast(other); |
| 8080 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 8112 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 8081 if (shared != shared_) return false; | 8113 if (shared != shared_) return false; |
| 8114 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( |
| 8115 Smi::cast(pair->get(2))->value()); |
| 8116 if (strict_mode != strict_mode_) return false; |
| 8082 String* source = String::cast(pair->get(1)); | 8117 String* source = String::cast(pair->get(1)); |
| 8083 return source->Equals(source_); | 8118 return source->Equals(source_); |
| 8084 } | 8119 } |
| 8085 | 8120 |
| 8086 static uint32_t StringSharedHashHelper(String* source, | 8121 static uint32_t StringSharedHashHelper(String* source, |
| 8087 SharedFunctionInfo* shared) { | 8122 SharedFunctionInfo* shared, |
| 8123 StrictModeFlag strict_mode) { |
| 8088 uint32_t hash = source->Hash(); | 8124 uint32_t hash = source->Hash(); |
| 8089 if (shared->HasSourceCode()) { | 8125 if (shared->HasSourceCode()) { |
| 8090 // Instead of using the SharedFunctionInfo pointer in the hash | 8126 // Instead of using the SharedFunctionInfo pointer in the hash |
| 8091 // code computation, we use a combination of the hash of the | 8127 // code computation, we use a combination of the hash of the |
| 8092 // script source code and the start and end positions. We do | 8128 // script source code and the start and end positions. We do |
| 8093 // this to ensure that the cache entries can survive garbage | 8129 // this to ensure that the cache entries can survive garbage |
| 8094 // collection. | 8130 // collection. |
| 8095 Script* script = Script::cast(shared->script()); | 8131 Script* script = Script::cast(shared->script()); |
| 8096 hash ^= String::cast(script->source())->Hash(); | 8132 hash ^= String::cast(script->source())->Hash(); |
| 8133 if (strict_mode == kStrictMode) hash ^= 0x8000; |
| 8097 hash += shared->start_position(); | 8134 hash += shared->start_position(); |
| 8098 } | 8135 } |
| 8099 return hash; | 8136 return hash; |
| 8100 } | 8137 } |
| 8101 | 8138 |
| 8102 uint32_t Hash() { | 8139 uint32_t Hash() { |
| 8103 return StringSharedHashHelper(source_, shared_); | 8140 return StringSharedHashHelper(source_, shared_, strict_mode_); |
| 8104 } | 8141 } |
| 8105 | 8142 |
| 8106 uint32_t HashForObject(Object* obj) { | 8143 uint32_t HashForObject(Object* obj) { |
| 8107 FixedArray* pair = FixedArray::cast(obj); | 8144 FixedArray* pair = FixedArray::cast(obj); |
| 8108 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 8145 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 8109 String* source = String::cast(pair->get(1)); | 8146 String* source = String::cast(pair->get(1)); |
| 8110 return StringSharedHashHelper(source, shared); | 8147 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( |
| 8148 Smi::cast(pair->get(2))->value()); |
| 8149 return StringSharedHashHelper(source, shared, strict_mode); |
| 8111 } | 8150 } |
| 8112 | 8151 |
| 8113 MUST_USE_RESULT MaybeObject* AsObject() { | 8152 MUST_USE_RESULT MaybeObject* AsObject() { |
| 8114 Object* obj; | 8153 Object* obj; |
| 8115 { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(2); | 8154 { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(3); |
| 8116 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8155 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8117 } | 8156 } |
| 8118 FixedArray* pair = FixedArray::cast(obj); | 8157 FixedArray* pair = FixedArray::cast(obj); |
| 8119 pair->set(0, shared_); | 8158 pair->set(0, shared_); |
| 8120 pair->set(1, source_); | 8159 pair->set(1, source_); |
| 8160 pair->set(2, Smi::FromInt(strict_mode_)); |
| 8121 return pair; | 8161 return pair; |
| 8122 } | 8162 } |
| 8123 | 8163 |
| 8124 private: | 8164 private: |
| 8125 String* source_; | 8165 String* source_; |
| 8126 SharedFunctionInfo* shared_; | 8166 SharedFunctionInfo* shared_; |
| 8167 StrictModeFlag strict_mode_; |
| 8127 }; | 8168 }; |
| 8128 | 8169 |
| 8129 | 8170 |
| 8130 // RegExpKey carries the source and flags of a regular expression as key. | 8171 // RegExpKey carries the source and flags of a regular expression as key. |
| 8131 class RegExpKey : public HashTableKey { | 8172 class RegExpKey : public HashTableKey { |
| 8132 public: | 8173 public: |
| 8133 RegExpKey(String* string, JSRegExp::Flags flags) | 8174 RegExpKey(String* string, JSRegExp::Flags flags) |
| 8134 : string_(string), | 8175 : string_(string), |
| 8135 flags_(Smi::FromInt(flags.value())) { } | 8176 flags_(Smi::FromInt(flags.value())) { } |
| 8136 | 8177 |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9069 | 9110 |
| 9070 Object* CompilationCacheTable::Lookup(String* src) { | 9111 Object* CompilationCacheTable::Lookup(String* src) { |
| 9071 Heap* heap = GetHeap(); | 9112 Heap* heap = GetHeap(); |
| 9072 StringKey key(src); | 9113 StringKey key(src); |
| 9073 int entry = FindEntry(&key); | 9114 int entry = FindEntry(&key); |
| 9074 if (entry == kNotFound) return heap->undefined_value(); | 9115 if (entry == kNotFound) return heap->undefined_value(); |
| 9075 return get(EntryToIndex(entry) + 1); | 9116 return get(EntryToIndex(entry) + 1); |
| 9076 } | 9117 } |
| 9077 | 9118 |
| 9078 | 9119 |
| 9079 Object* CompilationCacheTable::LookupEval(String* src, Context* context) { | 9120 Object* CompilationCacheTable::LookupEval(String* src, |
| 9080 StringSharedKey key(src, context->closure()->shared()); | 9121 Context* context, |
| 9122 StrictModeFlag strict_mode) { |
| 9123 StringSharedKey key(src, context->closure()->shared(), strict_mode); |
| 9081 int entry = FindEntry(&key); | 9124 int entry = FindEntry(&key); |
| 9082 if (entry == kNotFound) return GetHeap()->undefined_value(); | 9125 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 9083 return get(EntryToIndex(entry) + 1); | 9126 return get(EntryToIndex(entry) + 1); |
| 9084 } | 9127 } |
| 9085 | 9128 |
| 9086 | 9129 |
| 9087 Object* CompilationCacheTable::LookupRegExp(String* src, | 9130 Object* CompilationCacheTable::LookupRegExp(String* src, |
| 9088 JSRegExp::Flags flags) { | 9131 JSRegExp::Flags flags) { |
| 9089 Heap* heap = GetHeap(); | 9132 Heap* heap = GetHeap(); |
| 9090 RegExpKey key(src, flags); | 9133 RegExpKey key(src, flags); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 9106 int entry = cache->FindInsertionEntry(key.Hash()); | 9149 int entry = cache->FindInsertionEntry(key.Hash()); |
| 9107 cache->set(EntryToIndex(entry), src); | 9150 cache->set(EntryToIndex(entry), src); |
| 9108 cache->set(EntryToIndex(entry) + 1, value); | 9151 cache->set(EntryToIndex(entry) + 1, value); |
| 9109 cache->ElementAdded(); | 9152 cache->ElementAdded(); |
| 9110 return cache; | 9153 return cache; |
| 9111 } | 9154 } |
| 9112 | 9155 |
| 9113 | 9156 |
| 9114 MaybeObject* CompilationCacheTable::PutEval(String* src, | 9157 MaybeObject* CompilationCacheTable::PutEval(String* src, |
| 9115 Context* context, | 9158 Context* context, |
| 9116 Object* value) { | 9159 SharedFunctionInfo* value) { |
| 9117 StringSharedKey key(src, context->closure()->shared()); | 9160 StringSharedKey key(src, |
| 9161 context->closure()->shared(), |
| 9162 value->strict_mode() ? kStrictMode : kNonStrictMode); |
| 9118 Object* obj; | 9163 Object* obj; |
| 9119 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 9164 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 9120 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9165 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9121 } | 9166 } |
| 9122 | 9167 |
| 9123 CompilationCacheTable* cache = | 9168 CompilationCacheTable* cache = |
| 9124 reinterpret_cast<CompilationCacheTable*>(obj); | 9169 reinterpret_cast<CompilationCacheTable*>(obj); |
| 9125 int entry = cache->FindInsertionEntry(key.Hash()); | 9170 int entry = cache->FindInsertionEntry(key.Hash()); |
| 9126 | 9171 |
| 9127 Object* k; | 9172 Object* k; |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9966 if (break_point_objects()->IsUndefined()) return 0; | 10011 if (break_point_objects()->IsUndefined()) return 0; |
| 9967 // Single beak point. | 10012 // Single beak point. |
| 9968 if (!break_point_objects()->IsFixedArray()) return 1; | 10013 if (!break_point_objects()->IsFixedArray()) return 1; |
| 9969 // Multiple break points. | 10014 // Multiple break points. |
| 9970 return FixedArray::cast(break_point_objects())->length(); | 10015 return FixedArray::cast(break_point_objects())->length(); |
| 9971 } | 10016 } |
| 9972 #endif | 10017 #endif |
| 9973 | 10018 |
| 9974 | 10019 |
| 9975 } } // namespace v8::internal | 10020 } } // namespace v8::internal |
| OLD | NEW |