OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 | 121 |
122 #define BOOL_ACCESSORS(holder, field, name, offset) \ | 122 #define BOOL_ACCESSORS(holder, field, name, offset) \ |
123 bool holder::name() { \ | 123 bool holder::name() { \ |
124 return BooleanBit::get(field(), offset); \ | 124 return BooleanBit::get(field(), offset); \ |
125 } \ | 125 } \ |
126 void holder::set_##name(bool value) { \ | 126 void holder::set_##name(bool value) { \ |
127 set_##field(BooleanBit::set(field(), offset, value)); \ | 127 set_##field(BooleanBit::set(field(), offset, value)); \ |
128 } | 128 } |
129 | 129 |
130 | 130 |
| 131 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, |
| 132 ElementsKind to_kind) { |
| 133 if (to_kind == FAST_ELEMENTS) { |
| 134 return from_kind == FAST_SMI_ONLY_ELEMENTS || |
| 135 from_kind == FAST_DOUBLE_ELEMENTS; |
| 136 } else { |
| 137 return to_kind == FAST_DOUBLE_ELEMENTS && |
| 138 from_kind == FAST_SMI_ONLY_ELEMENTS; |
| 139 } |
| 140 } |
| 141 |
| 142 |
131 bool Object::IsFixedArrayBase() { | 143 bool Object::IsFixedArrayBase() { |
132 return IsFixedArray() || IsFixedDoubleArray(); | 144 return IsFixedArray() || IsFixedDoubleArray(); |
133 } | 145 } |
134 | 146 |
135 | 147 |
136 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { | 148 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { |
137 // There is a constraint on the object; check. | 149 // There is a constraint on the object; check. |
138 if (!this->IsJSObject()) return false; | 150 if (!this->IsJSObject()) return false; |
139 // Fetch the constructor function of the object. | 151 // Fetch the constructor function of the object. |
140 Object* cons_obj = JSObject::cast(this)->map()->constructor(); | 152 Object* cons_obj = JSObject::cast(this)->map()->constructor(); |
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 } | 1237 } |
1226 return true; | 1238 return true; |
1227 } | 1239 } |
1228 | 1240 |
1229 | 1241 |
1230 FixedArrayBase* JSObject::elements() { | 1242 FixedArrayBase* JSObject::elements() { |
1231 Object* array = READ_FIELD(this, kElementsOffset); | 1243 Object* array = READ_FIELD(this, kElementsOffset); |
1232 return static_cast<FixedArrayBase*>(array); | 1244 return static_cast<FixedArrayBase*>(array); |
1233 } | 1245 } |
1234 | 1246 |
1235 | 1247 void JSObject::ValidateSmiOnlyElements() { |
1236 void JSObject::ValidateElements() { | |
1237 #if DEBUG | 1248 #if DEBUG |
1238 if (FLAG_enable_slow_asserts) { | 1249 if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) { |
1239 ElementsAccessor* accessor = GetElementsAccessor(); | 1250 Heap* heap = GetHeap(); |
1240 accessor->Validate(this); | 1251 // Don't use elements, since integrity checks will fail if there |
| 1252 // are filler pointers in the array. |
| 1253 FixedArray* fixed_array = |
| 1254 reinterpret_cast<FixedArray*>(READ_FIELD(this, kElementsOffset)); |
| 1255 Map* map = fixed_array->map(); |
| 1256 // Arrays that have been shifted in place can't be verified. |
| 1257 if (map != heap->raw_unchecked_one_pointer_filler_map() && |
| 1258 map != heap->raw_unchecked_two_pointer_filler_map() && |
| 1259 map != heap->free_space_map()) { |
| 1260 for (int i = 0; i < fixed_array->length(); i++) { |
| 1261 Object* current = fixed_array->get(i); |
| 1262 ASSERT(current->IsSmi() || current->IsTheHole()); |
| 1263 } |
| 1264 } |
1241 } | 1265 } |
1242 #endif | 1266 #endif |
1243 } | 1267 } |
1244 | 1268 |
1245 | 1269 |
1246 MaybeObject* JSObject::EnsureCanContainHeapObjectElements() { | 1270 MaybeObject* JSObject::EnsureCanContainHeapObjectElements() { |
1247 ValidateElements(); | 1271 #if DEBUG |
1248 ElementsKind elements_kind = map()->elements_kind(); | 1272 ValidateSmiOnlyElements(); |
1249 if (!IsFastObjectElementsKind(elements_kind)) { | 1273 #endif |
1250 if (IsFastHoleyElementsKind(elements_kind)) { | 1274 if ((map()->elements_kind() != FAST_ELEMENTS)) { |
1251 return TransitionElementsKind(FAST_HOLEY_ELEMENTS); | 1275 return TransitionElementsKind(FAST_ELEMENTS); |
1252 } else { | |
1253 return TransitionElementsKind(FAST_ELEMENTS); | |
1254 } | |
1255 } | 1276 } |
1256 return this; | 1277 return this; |
1257 } | 1278 } |
1258 | 1279 |
1259 | 1280 |
1260 MaybeObject* JSObject::EnsureCanContainElements(Object** objects, | 1281 MaybeObject* JSObject::EnsureCanContainElements(Object** objects, |
1261 uint32_t count, | 1282 uint32_t count, |
1262 EnsureElementsMode mode) { | 1283 EnsureElementsMode mode) { |
1263 ElementsKind current_kind = map()->elements_kind(); | 1284 ElementsKind current_kind = map()->elements_kind(); |
1264 ElementsKind target_kind = current_kind; | 1285 ElementsKind target_kind = current_kind; |
1265 ASSERT(mode != ALLOW_COPIED_DOUBLE_ELEMENTS); | 1286 ASSERT(mode != ALLOW_COPIED_DOUBLE_ELEMENTS); |
1266 bool is_holey = IsFastHoleyElementsKind(current_kind); | 1287 if (current_kind == FAST_ELEMENTS) return this; |
1267 if (current_kind == FAST_HOLEY_ELEMENTS) return this; | 1288 |
1268 Heap* heap = GetHeap(); | 1289 Heap* heap = GetHeap(); |
1269 Object* the_hole = heap->the_hole_value(); | 1290 Object* the_hole = heap->the_hole_value(); |
1270 Object* heap_number_map = heap->heap_number_map(); | 1291 Object* heap_number_map = heap->heap_number_map(); |
1271 for (uint32_t i = 0; i < count; ++i) { | 1292 for (uint32_t i = 0; i < count; ++i) { |
1272 Object* current = *objects++; | 1293 Object* current = *objects++; |
1273 if (current == the_hole) { | 1294 if (!current->IsSmi() && current != the_hole) { |
1274 is_holey = true; | |
1275 target_kind = GetHoleyElementsKind(target_kind); | |
1276 } else if (!current->IsSmi()) { | |
1277 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && | 1295 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && |
1278 HeapObject::cast(current)->map() == heap_number_map && | 1296 HeapObject::cast(current)->map() == heap_number_map) { |
1279 IsFastSmiElementsKind(target_kind)) { | 1297 target_kind = FAST_DOUBLE_ELEMENTS; |
1280 if (is_holey) { | |
1281 target_kind = FAST_HOLEY_DOUBLE_ELEMENTS; | |
1282 } else { | |
1283 target_kind = FAST_DOUBLE_ELEMENTS; | |
1284 } | |
1285 } else { | 1298 } else { |
1286 if (!current->IsNumber()) { | 1299 target_kind = FAST_ELEMENTS; |
1287 if (is_holey) { | 1300 break; |
1288 target_kind = FAST_HOLEY_ELEMENTS; | |
1289 break; | |
1290 } else { | |
1291 target_kind = FAST_ELEMENTS; | |
1292 } | |
1293 } | |
1294 } | 1301 } |
1295 } | 1302 } |
1296 } | 1303 } |
1297 | 1304 |
1298 if (target_kind != current_kind) { | 1305 if (target_kind != current_kind) { |
1299 return TransitionElementsKind(target_kind); | 1306 return TransitionElementsKind(target_kind); |
1300 } | 1307 } |
1301 return this; | 1308 return this; |
1302 } | 1309 } |
1303 | 1310 |
1304 | 1311 |
1305 MaybeObject* JSObject::EnsureCanContainElements(FixedArrayBase* elements, | 1312 MaybeObject* JSObject::EnsureCanContainElements(FixedArrayBase* elements, |
1306 uint32_t length, | |
1307 EnsureElementsMode mode) { | 1313 EnsureElementsMode mode) { |
1308 if (elements->map() != GetHeap()->fixed_double_array_map()) { | 1314 if (elements->map() != GetHeap()->fixed_double_array_map()) { |
1309 ASSERT(elements->map() == GetHeap()->fixed_array_map() || | 1315 ASSERT(elements->map() == GetHeap()->fixed_array_map() || |
1310 elements->map() == GetHeap()->fixed_cow_array_map()); | 1316 elements->map() == GetHeap()->fixed_cow_array_map()); |
1311 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) { | 1317 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) { |
1312 mode = DONT_ALLOW_DOUBLE_ELEMENTS; | 1318 mode = DONT_ALLOW_DOUBLE_ELEMENTS; |
1313 } | 1319 } |
1314 Object** objects = FixedArray::cast(elements)->GetFirstElementAddress(); | 1320 Object** objects = FixedArray::cast(elements)->GetFirstElementAddress(); |
1315 return EnsureCanContainElements(objects, length, mode); | 1321 return EnsureCanContainElements(objects, elements->length(), mode); |
1316 } | 1322 } |
1317 | 1323 |
1318 ASSERT(mode == ALLOW_COPIED_DOUBLE_ELEMENTS); | 1324 ASSERT(mode == ALLOW_COPIED_DOUBLE_ELEMENTS); |
1319 if (GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) { | 1325 if (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { |
1320 return TransitionElementsKind(FAST_HOLEY_DOUBLE_ELEMENTS); | |
1321 } else if (GetElementsKind() == FAST_SMI_ELEMENTS) { | |
1322 FixedDoubleArray* double_array = FixedDoubleArray::cast(elements); | |
1323 for (uint32_t i = 0; i < length; ++i) { | |
1324 if (double_array->is_the_hole(i)) { | |
1325 return TransitionElementsKind(FAST_HOLEY_DOUBLE_ELEMENTS); | |
1326 } | |
1327 } | |
1328 return TransitionElementsKind(FAST_DOUBLE_ELEMENTS); | 1326 return TransitionElementsKind(FAST_DOUBLE_ELEMENTS); |
1329 } | 1327 } |
1330 | 1328 |
1331 return this; | 1329 return this; |
1332 } | 1330 } |
1333 | 1331 |
1334 | 1332 |
1335 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate, | 1333 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate, |
1336 ElementsKind to_kind) { | 1334 ElementsKind to_kind) { |
1337 Map* current_map = map(); | 1335 Map* current_map = map(); |
1338 ElementsKind from_kind = current_map->elements_kind(); | 1336 ElementsKind from_kind = current_map->elements_kind(); |
| 1337 |
1339 if (from_kind == to_kind) return current_map; | 1338 if (from_kind == to_kind) return current_map; |
1340 | 1339 |
1341 Context* global_context = isolate->context()->global_context(); | 1340 Context* global_context = isolate->context()->global_context(); |
1342 Object* maybe_array_maps = global_context->js_array_maps(); | 1341 if (current_map == global_context->smi_js_array_map()) { |
1343 if (maybe_array_maps->IsFixedArray()) { | 1342 if (to_kind == FAST_ELEMENTS) { |
1344 FixedArray* array_maps = FixedArray::cast(maybe_array_maps); | 1343 return global_context->object_js_array_map(); |
1345 if (array_maps->get(from_kind) == current_map) { | 1344 } else { |
1346 Object* maybe_transitioned_map = array_maps->get(to_kind); | 1345 if (to_kind == FAST_DOUBLE_ELEMENTS) { |
1347 if (maybe_transitioned_map->IsMap()) { | 1346 return global_context->double_js_array_map(); |
1348 return Map::cast(maybe_transitioned_map); | 1347 } else { |
| 1348 ASSERT(to_kind == DICTIONARY_ELEMENTS); |
1349 } | 1349 } |
1350 } | 1350 } |
1351 } | 1351 } |
1352 | |
1353 return GetElementsTransitionMapSlow(to_kind); | 1352 return GetElementsTransitionMapSlow(to_kind); |
1354 } | 1353 } |
1355 | 1354 |
1356 | 1355 |
1357 void JSObject::set_map_and_elements(Map* new_map, | 1356 void JSObject::set_map_and_elements(Map* new_map, |
1358 FixedArrayBase* value, | 1357 FixedArrayBase* value, |
1359 WriteBarrierMode mode) { | 1358 WriteBarrierMode mode) { |
1360 ASSERT(value->HasValidElements()); | 1359 ASSERT(value->HasValidElements()); |
| 1360 #ifdef DEBUG |
| 1361 ValidateSmiOnlyElements(); |
| 1362 #endif |
1361 if (new_map != NULL) { | 1363 if (new_map != NULL) { |
1362 if (mode == UPDATE_WRITE_BARRIER) { | 1364 if (mode == UPDATE_WRITE_BARRIER) { |
1363 set_map(new_map); | 1365 set_map(new_map); |
1364 } else { | 1366 } else { |
1365 ASSERT(mode == SKIP_WRITE_BARRIER); | 1367 ASSERT(mode == SKIP_WRITE_BARRIER); |
1366 set_map_no_write_barrier(new_map); | 1368 set_map_no_write_barrier(new_map); |
1367 } | 1369 } |
1368 } | 1370 } |
1369 ASSERT((map()->has_fast_smi_or_object_elements() || | 1371 ASSERT((map()->has_fast_elements() || |
| 1372 map()->has_fast_smi_only_elements() || |
1370 (value == GetHeap()->empty_fixed_array())) == | 1373 (value == GetHeap()->empty_fixed_array())) == |
1371 (value->map() == GetHeap()->fixed_array_map() || | 1374 (value->map() == GetHeap()->fixed_array_map() || |
1372 value->map() == GetHeap()->fixed_cow_array_map())); | 1375 value->map() == GetHeap()->fixed_cow_array_map())); |
1373 ASSERT((value == GetHeap()->empty_fixed_array()) || | 1376 ASSERT((value == GetHeap()->empty_fixed_array()) || |
1374 (map()->has_fast_double_elements() == value->IsFixedDoubleArray())); | 1377 (map()->has_fast_double_elements() == value->IsFixedDoubleArray())); |
1375 WRITE_FIELD(this, kElementsOffset, value); | 1378 WRITE_FIELD(this, kElementsOffset, value); |
1376 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); | 1379 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); |
1377 } | 1380 } |
1378 | 1381 |
1379 | 1382 |
1380 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { | 1383 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { |
1381 set_map_and_elements(NULL, value, mode); | 1384 set_map_and_elements(NULL, value, mode); |
1382 } | 1385 } |
1383 | 1386 |
1384 | 1387 |
1385 void JSObject::initialize_properties() { | 1388 void JSObject::initialize_properties() { |
1386 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 1389 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
1387 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); | 1390 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); |
1388 } | 1391 } |
1389 | 1392 |
1390 | 1393 |
1391 void JSObject::initialize_elements() { | 1394 void JSObject::initialize_elements() { |
1392 ASSERT(map()->has_fast_smi_or_object_elements() || | 1395 ASSERT(map()->has_fast_elements() || |
| 1396 map()->has_fast_smi_only_elements() || |
1393 map()->has_fast_double_elements()); | 1397 map()->has_fast_double_elements()); |
1394 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 1398 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
1395 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); | 1399 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); |
1396 } | 1400 } |
1397 | 1401 |
1398 | 1402 |
1399 MaybeObject* JSObject::ResetElements() { | 1403 MaybeObject* JSObject::ResetElements() { |
1400 Object* obj; | 1404 Object* obj; |
1401 ElementsKind elements_kind = GetInitialFastElementsKind(); | 1405 ElementsKind elements_kind = FLAG_smi_only_arrays |
1402 if (!FLAG_smi_only_arrays) { | 1406 ? FAST_SMI_ONLY_ELEMENTS |
1403 elements_kind = FastSmiToObjectElementsKind(elements_kind); | 1407 : FAST_ELEMENTS; |
1404 } | |
1405 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 1408 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), |
1406 elements_kind); | 1409 elements_kind); |
1407 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1410 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1408 set_map(Map::cast(obj)); | 1411 set_map(Map::cast(obj)); |
1409 initialize_elements(); | 1412 initialize_elements(); |
1410 return this; | 1413 return this; |
1411 } | 1414 } |
1412 | 1415 |
1413 | 1416 |
1414 ACCESSORS(Oddball, to_string, String, kToStringOffset) | 1417 ACCESSORS(Oddball, to_string, String, kToStringOffset) |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1666 return reinterpret_cast<FixedArrayBase*>(object); | 1669 return reinterpret_cast<FixedArrayBase*>(object); |
1667 } | 1670 } |
1668 | 1671 |
1669 | 1672 |
1670 Object* FixedArray::get(int index) { | 1673 Object* FixedArray::get(int index) { |
1671 ASSERT(index >= 0 && index < this->length()); | 1674 ASSERT(index >= 0 && index < this->length()); |
1672 return READ_FIELD(this, kHeaderSize + index * kPointerSize); | 1675 return READ_FIELD(this, kHeaderSize + index * kPointerSize); |
1673 } | 1676 } |
1674 | 1677 |
1675 | 1678 |
1676 bool FixedArray::is_the_hole(int index) { | |
1677 return get(index) == GetHeap()->the_hole_value(); | |
1678 } | |
1679 | |
1680 | |
1681 void FixedArray::set(int index, Smi* value) { | 1679 void FixedArray::set(int index, Smi* value) { |
1682 ASSERT(map() != HEAP->fixed_cow_array_map()); | 1680 ASSERT(map() != HEAP->fixed_cow_array_map()); |
1683 ASSERT(index >= 0 && index < this->length()); | 1681 ASSERT(index >= 0 && index < this->length()); |
1684 ASSERT(reinterpret_cast<Object*>(value)->IsSmi()); | 1682 ASSERT(reinterpret_cast<Object*>(value)->IsSmi()); |
1685 int offset = kHeaderSize + index * kPointerSize; | 1683 int offset = kHeaderSize + index * kPointerSize; |
1686 WRITE_FIELD(this, offset, value); | 1684 WRITE_FIELD(this, offset, value); |
1687 } | 1685 } |
1688 | 1686 |
1689 | 1687 |
1690 void FixedArray::set(int index, Object* value) { | 1688 void FixedArray::set(int index, Object* value) { |
(...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2852 } | 2850 } |
2853 | 2851 |
2854 | 2852 |
2855 bool Map::has_non_instance_prototype() { | 2853 bool Map::has_non_instance_prototype() { |
2856 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0; | 2854 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0; |
2857 } | 2855 } |
2858 | 2856 |
2859 | 2857 |
2860 void Map::set_function_with_prototype(bool value) { | 2858 void Map::set_function_with_prototype(bool value) { |
2861 if (value) { | 2859 if (value) { |
2862 set_bit_field3(bit_field3() | (1 << kFunctionWithPrototype)); | 2860 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype)); |
2863 } else { | 2861 } else { |
2864 set_bit_field3(bit_field3() & ~(1 << kFunctionWithPrototype)); | 2862 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype)); |
2865 } | 2863 } |
2866 } | 2864 } |
2867 | 2865 |
2868 | 2866 |
2869 bool Map::function_with_prototype() { | 2867 bool Map::function_with_prototype() { |
2870 return ((1 << kFunctionWithPrototype) & bit_field3()) != 0; | 2868 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0; |
2871 } | 2869 } |
2872 | 2870 |
2873 | 2871 |
2874 void Map::set_is_access_check_needed(bool access_check_needed) { | 2872 void Map::set_is_access_check_needed(bool access_check_needed) { |
2875 if (access_check_needed) { | 2873 if (access_check_needed) { |
2876 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded)); | 2874 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded)); |
2877 } else { | 2875 } else { |
2878 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded)); | 2876 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded)); |
2879 } | 2877 } |
2880 } | 2878 } |
(...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4003 } | 4001 } |
4004 | 4002 |
4005 | 4003 |
4006 MaybeObject* JSFunction::set_initial_map_and_cache_transitions( | 4004 MaybeObject* JSFunction::set_initial_map_and_cache_transitions( |
4007 Map* initial_map) { | 4005 Map* initial_map) { |
4008 Context* global_context = context()->global_context(); | 4006 Context* global_context = context()->global_context(); |
4009 Object* array_function = | 4007 Object* array_function = |
4010 global_context->get(Context::ARRAY_FUNCTION_INDEX); | 4008 global_context->get(Context::ARRAY_FUNCTION_INDEX); |
4011 if (array_function->IsJSFunction() && | 4009 if (array_function->IsJSFunction() && |
4012 this == JSFunction::cast(array_function)) { | 4010 this == JSFunction::cast(array_function)) { |
4013 // Replace all of the cached initial array maps in the global context with | 4011 ASSERT(initial_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); |
4014 // the appropriate transitioned elements kind maps. | |
4015 Heap* heap = GetHeap(); | |
4016 MaybeObject* maybe_maps = | |
4017 heap->AllocateFixedArrayWithHoles(kElementsKindCount); | |
4018 FixedArray* maps; | |
4019 if (!maybe_maps->To(&maps)) return maybe_maps; | |
4020 | 4012 |
4021 Map* current_map = initial_map; | 4013 MaybeObject* maybe_map = initial_map->CopyDropTransitions(); |
4022 ElementsKind kind = current_map->elements_kind(); | 4014 Map* new_double_map = NULL; |
4023 ASSERT(kind == GetInitialFastElementsKind()); | 4015 if (!maybe_map->To<Map>(&new_double_map)) return maybe_map; |
4024 maps->set(kind, current_map); | 4016 new_double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS); |
4025 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; | 4017 maybe_map = initial_map->AddElementsTransition(FAST_DOUBLE_ELEMENTS, |
4026 i < kFastElementsKindCount; ++i) { | 4018 new_double_map); |
4027 ElementsKind transitioned_kind = GetFastElementsKindFromSequenceIndex(i); | 4019 if (maybe_map->IsFailure()) return maybe_map; |
4028 MaybeObject* maybe_new_map = current_map->CopyDropTransitions(); | 4020 |
4029 Map* new_map = NULL; | 4021 maybe_map = new_double_map->CopyDropTransitions(); |
4030 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | 4022 Map* new_object_map = NULL; |
4031 new_map->set_elements_kind(transitioned_kind); | 4023 if (!maybe_map->To<Map>(&new_object_map)) return maybe_map; |
4032 maybe_new_map = current_map->AddElementsTransition(transitioned_kind, | 4024 new_object_map->set_elements_kind(FAST_ELEMENTS); |
4033 new_map); | 4025 maybe_map = new_double_map->AddElementsTransition(FAST_ELEMENTS, |
4034 if (maybe_new_map->IsFailure()) return maybe_new_map; | 4026 new_object_map); |
4035 maps->set(transitioned_kind, new_map); | 4027 if (maybe_map->IsFailure()) return maybe_map; |
4036 current_map = new_map; | 4028 |
4037 } | 4029 global_context->set_smi_js_array_map(initial_map); |
4038 global_context->set_js_array_maps(maps); | 4030 global_context->set_double_js_array_map(new_double_map); |
| 4031 global_context->set_object_js_array_map(new_object_map); |
4039 } | 4032 } |
4040 set_initial_map(initial_map); | 4033 set_initial_map(initial_map); |
4041 return this; | 4034 return this; |
4042 } | 4035 } |
4043 | 4036 |
4044 | 4037 |
4045 bool JSFunction::has_initial_map() { | 4038 bool JSFunction::has_initial_map() { |
4046 return prototype_or_initial_map()->IsMap(); | 4039 return prototype_or_initial_map()->IsMap(); |
4047 } | 4040 } |
4048 | 4041 |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4364 } | 4357 } |
4365 } | 4358 } |
4366 | 4359 |
4367 | 4360 |
4368 ElementsKind JSObject::GetElementsKind() { | 4361 ElementsKind JSObject::GetElementsKind() { |
4369 ElementsKind kind = map()->elements_kind(); | 4362 ElementsKind kind = map()->elements_kind(); |
4370 #if DEBUG | 4363 #if DEBUG |
4371 FixedArrayBase* fixed_array = | 4364 FixedArrayBase* fixed_array = |
4372 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset)); | 4365 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset)); |
4373 Map* map = fixed_array->map(); | 4366 Map* map = fixed_array->map(); |
4374 ASSERT((IsFastSmiOrObjectElementsKind(kind) && | 4367 ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) && |
4375 (map == GetHeap()->fixed_array_map() || | 4368 (map == GetHeap()->fixed_array_map() || |
4376 map == GetHeap()->fixed_cow_array_map())) || | 4369 map == GetHeap()->fixed_cow_array_map())) || |
4377 (IsFastDoubleElementsKind(kind) && | 4370 (kind == FAST_DOUBLE_ELEMENTS && |
4378 (fixed_array->IsFixedDoubleArray() || | 4371 (fixed_array->IsFixedDoubleArray() || |
4379 fixed_array == GetHeap()->empty_fixed_array())) || | 4372 fixed_array == GetHeap()->empty_fixed_array())) || |
4380 (kind == DICTIONARY_ELEMENTS && | 4373 (kind == DICTIONARY_ELEMENTS && |
4381 fixed_array->IsFixedArray() && | 4374 fixed_array->IsFixedArray() && |
4382 fixed_array->IsDictionary()) || | 4375 fixed_array->IsDictionary()) || |
4383 (kind > DICTIONARY_ELEMENTS)); | 4376 (kind > DICTIONARY_ELEMENTS)); |
4384 ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) || | 4377 ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) || |
4385 (elements()->IsFixedArray() && elements()->length() >= 2)); | 4378 (elements()->IsFixedArray() && elements()->length() >= 2)); |
4386 #endif | 4379 #endif |
4387 return kind; | 4380 return kind; |
4388 } | 4381 } |
4389 | 4382 |
4390 | 4383 |
4391 ElementsAccessor* JSObject::GetElementsAccessor() { | 4384 ElementsAccessor* JSObject::GetElementsAccessor() { |
4392 return ElementsAccessor::ForKind(GetElementsKind()); | 4385 return ElementsAccessor::ForKind(GetElementsKind()); |
4393 } | 4386 } |
4394 | 4387 |
4395 | 4388 |
4396 bool JSObject::HasFastObjectElements() { | 4389 bool JSObject::HasFastElements() { |
4397 return IsFastObjectElementsKind(GetElementsKind()); | 4390 return GetElementsKind() == FAST_ELEMENTS; |
4398 } | 4391 } |
4399 | 4392 |
4400 | 4393 |
4401 bool JSObject::HasFastSmiElements() { | 4394 bool JSObject::HasFastSmiOnlyElements() { |
4402 return IsFastSmiElementsKind(GetElementsKind()); | 4395 return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS; |
4403 } | 4396 } |
4404 | 4397 |
4405 | 4398 |
4406 bool JSObject::HasFastSmiOrObjectElements() { | 4399 bool JSObject::HasFastTypeElements() { |
4407 return IsFastSmiOrObjectElementsKind(GetElementsKind()); | 4400 ElementsKind elements_kind = GetElementsKind(); |
| 4401 return elements_kind == FAST_SMI_ONLY_ELEMENTS || |
| 4402 elements_kind == FAST_ELEMENTS; |
4408 } | 4403 } |
4409 | 4404 |
4410 | 4405 |
4411 bool JSObject::HasFastDoubleElements() { | 4406 bool JSObject::HasFastDoubleElements() { |
4412 return IsFastDoubleElementsKind(GetElementsKind()); | 4407 return GetElementsKind() == FAST_DOUBLE_ELEMENTS; |
4413 } | 4408 } |
4414 | 4409 |
4415 | 4410 |
4416 bool JSObject::HasFastHoleyElements() { | |
4417 return IsFastHoleyElementsKind(GetElementsKind()); | |
4418 } | |
4419 | |
4420 | |
4421 bool JSObject::HasDictionaryElements() { | 4411 bool JSObject::HasDictionaryElements() { |
4422 return GetElementsKind() == DICTIONARY_ELEMENTS; | 4412 return GetElementsKind() == DICTIONARY_ELEMENTS; |
4423 } | 4413 } |
4424 | 4414 |
4425 | 4415 |
4426 bool JSObject::HasNonStrictArgumentsElements() { | 4416 bool JSObject::HasNonStrictArgumentsElements() { |
4427 return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS; | 4417 return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS; |
4428 } | 4418 } |
4429 | 4419 |
4430 | 4420 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4464 return map()->has_named_interceptor(); | 4454 return map()->has_named_interceptor(); |
4465 } | 4455 } |
4466 | 4456 |
4467 | 4457 |
4468 bool JSObject::HasIndexedInterceptor() { | 4458 bool JSObject::HasIndexedInterceptor() { |
4469 return map()->has_indexed_interceptor(); | 4459 return map()->has_indexed_interceptor(); |
4470 } | 4460 } |
4471 | 4461 |
4472 | 4462 |
4473 MaybeObject* JSObject::EnsureWritableFastElements() { | 4463 MaybeObject* JSObject::EnsureWritableFastElements() { |
4474 ASSERT(HasFastSmiOrObjectElements()); | 4464 ASSERT(HasFastTypeElements()); |
4475 FixedArray* elems = FixedArray::cast(elements()); | 4465 FixedArray* elems = FixedArray::cast(elements()); |
4476 Isolate* isolate = GetIsolate(); | 4466 Isolate* isolate = GetIsolate(); |
4477 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; | 4467 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; |
4478 Object* writable_elems; | 4468 Object* writable_elems; |
4479 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap( | 4469 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap( |
4480 elems, isolate->heap()->fixed_array_map()); | 4470 elems, isolate->heap()->fixed_array_map()); |
4481 if (!maybe_writable_elems->ToObject(&writable_elems)) { | 4471 if (!maybe_writable_elems->ToObject(&writable_elems)) { |
4482 return maybe_writable_elems; | 4472 return maybe_writable_elems; |
4483 } | 4473 } |
4484 } | 4474 } |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4822 // No write barrier is needed since empty_fixed_array is not in new space. | 4812 // No write barrier is needed since empty_fixed_array is not in new space. |
4823 // Please note this function is used during marking: | 4813 // Please note this function is used during marking: |
4824 // - MarkCompactCollector::MarkUnmarkedObject | 4814 // - MarkCompactCollector::MarkUnmarkedObject |
4825 // - IncrementalMarking::Step | 4815 // - IncrementalMarking::Step |
4826 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array())); | 4816 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array())); |
4827 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array()); | 4817 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array()); |
4828 } | 4818 } |
4829 | 4819 |
4830 | 4820 |
4831 void JSArray::EnsureSize(int required_size) { | 4821 void JSArray::EnsureSize(int required_size) { |
4832 ASSERT(HasFastSmiOrObjectElements()); | 4822 ASSERT(HasFastTypeElements()); |
4833 FixedArray* elts = FixedArray::cast(elements()); | 4823 FixedArray* elts = FixedArray::cast(elements()); |
4834 const int kArraySizeThatFitsComfortablyInNewSpace = 128; | 4824 const int kArraySizeThatFitsComfortablyInNewSpace = 128; |
4835 if (elts->length() < required_size) { | 4825 if (elts->length() < required_size) { |
4836 // Doubling in size would be overkill, but leave some slack to avoid | 4826 // Doubling in size would be overkill, but leave some slack to avoid |
4837 // constantly growing. | 4827 // constantly growing. |
4838 Expand(required_size + (required_size >> 3)); | 4828 Expand(required_size + (required_size >> 3)); |
4839 // It's a performance benefit to keep a frequently used array in new-space. | 4829 // It's a performance benefit to keep a frequently used array in new-space. |
4840 } else if (!GetHeap()->new_space()->Contains(elts) && | 4830 } else if (!GetHeap()->new_space()->Contains(elts) && |
4841 required_size < kArraySizeThatFitsComfortablyInNewSpace) { | 4831 required_size < kArraySizeThatFitsComfortablyInNewSpace) { |
4842 // Expand will allocate a new backing store in new space even if the size | 4832 // Expand will allocate a new backing store in new space even if the size |
(...skipping 11 matching lines...) Expand all Loading... |
4854 | 4844 |
4855 bool JSArray::AllowsSetElementsLength() { | 4845 bool JSArray::AllowsSetElementsLength() { |
4856 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray(); | 4846 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray(); |
4857 ASSERT(result == !HasExternalArrayElements()); | 4847 ASSERT(result == !HasExternalArrayElements()); |
4858 return result; | 4848 return result; |
4859 } | 4849 } |
4860 | 4850 |
4861 | 4851 |
4862 MaybeObject* JSArray::SetContent(FixedArrayBase* storage) { | 4852 MaybeObject* JSArray::SetContent(FixedArrayBase* storage) { |
4863 MaybeObject* maybe_result = EnsureCanContainElements( | 4853 MaybeObject* maybe_result = EnsureCanContainElements( |
4864 storage, storage->length(), ALLOW_COPIED_DOUBLE_ELEMENTS); | 4854 storage, ALLOW_COPIED_DOUBLE_ELEMENTS); |
4865 if (maybe_result->IsFailure()) return maybe_result; | 4855 if (maybe_result->IsFailure()) return maybe_result; |
4866 ASSERT((storage->map() == GetHeap()->fixed_double_array_map() && | 4856 ASSERT((storage->map() == GetHeap()->fixed_double_array_map() && |
4867 IsFastDoubleElementsKind(GetElementsKind())) || | 4857 GetElementsKind() == FAST_DOUBLE_ELEMENTS) || |
4868 ((storage->map() != GetHeap()->fixed_double_array_map()) && | 4858 ((storage->map() != GetHeap()->fixed_double_array_map()) && |
4869 (IsFastObjectElementsKind(GetElementsKind()) || | 4859 ((GetElementsKind() == FAST_ELEMENTS) || |
4870 (IsFastSmiElementsKind(GetElementsKind()) && | 4860 (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS && |
4871 FixedArray::cast(storage)->ContainsOnlySmisOrHoles())))); | 4861 FixedArray::cast(storage)->ContainsOnlySmisOrHoles())))); |
4872 set_elements(storage); | 4862 set_elements(storage); |
4873 set_length(Smi::FromInt(storage->length())); | 4863 set_length(Smi::FromInt(storage->length())); |
4874 return this; | 4864 return this; |
4875 } | 4865 } |
4876 | 4866 |
4877 | 4867 |
4878 MaybeObject* FixedArray::Copy() { | 4868 MaybeObject* FixedArray::Copy() { |
4879 if (length() == 0) return this; | 4869 if (length() == 0) return this; |
4880 return GetHeap()->CopyFixedArray(this); | 4870 return GetHeap()->CopyFixedArray(this); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5037 #undef WRITE_UINT32_FIELD | 5027 #undef WRITE_UINT32_FIELD |
5038 #undef READ_SHORT_FIELD | 5028 #undef READ_SHORT_FIELD |
5039 #undef WRITE_SHORT_FIELD | 5029 #undef WRITE_SHORT_FIELD |
5040 #undef READ_BYTE_FIELD | 5030 #undef READ_BYTE_FIELD |
5041 #undef WRITE_BYTE_FIELD | 5031 #undef WRITE_BYTE_FIELD |
5042 | 5032 |
5043 | 5033 |
5044 } } // namespace v8::internal | 5034 } } // namespace v8::internal |
5045 | 5035 |
5046 #endif // V8_OBJECTS_INL_H_ | 5036 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |