OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1170 accumulator->Put('>'); | 1170 accumulator->Put('>'); |
1171 break; | 1171 break; |
1172 } | 1172 } |
1173 } | 1173 } |
1174 } | 1174 } |
1175 | 1175 |
1176 | 1176 |
1177 void JSObject::PrintElementsTransition( | 1177 void JSObject::PrintElementsTransition( |
1178 FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements, | 1178 FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements, |
1179 ElementsKind to_kind, FixedArrayBase* to_elements) { | 1179 ElementsKind to_kind, FixedArrayBase* to_elements) { |
1180 PrintF(file, "elements transition ["); | |
1181 PrintElementsKind(file, from_kind); | |
1182 PrintF(file, " -> "); | |
1183 PrintElementsKind(file, to_kind); | |
1184 PrintF(file, "] in "); | |
1185 JavaScriptFrame::PrintTop(file, false, true); | |
1186 PrintF(file, " for "); | |
1187 ShortPrint(file); | |
1188 PrintF(file, " from "); | |
1189 from_elements->ShortPrint(file); | |
1190 PrintF(file, " to "); | |
1191 to_elements->ShortPrint(file); | |
1192 PrintF(file, "\n"); | |
1193 } | |
1194 | |
1195 enum { | |
1196 kFastElementArrayBiasIncrement = 1, | |
1197 kFastElementArrayBiasThreshold = 3, | |
1198 kFastSmiOnlyElementArrayBiasIncrement = -10, | |
1199 kFastSmiOnlyElementArrayBiasThreshold = -30 | |
1200 }; | |
1201 | |
1202 | |
1203 void JSObject::RecordElementsTransition( | |
1204 ElementsKind from_kind, FixedArrayBase* from_elements, | |
1205 ElementsKind to_kind, FixedArrayBase* to_elements) { | |
1180 if (from_kind != to_kind) { | 1206 if (from_kind != to_kind) { |
1181 PrintF(file, "elements transition ["); | 1207 if (FLAG_trace_elements_transitions) { |
1182 PrintElementsKind(file, from_kind); | 1208 PrintElementsTransition(stdout, from_kind, from_elements, |
1183 PrintF(file, " -> "); | 1209 to_kind, to_elements); |
1184 PrintElementsKind(file, to_kind); | 1210 } |
1185 PrintF(file, "] in "); | 1211 } |
1186 JavaScriptFrame::PrintTop(file, false, true); | 1212 |
1187 PrintF(file, " for "); | 1213 // Use elements transitions to determine whether Array() should by default |
1188 ShortPrint(file); | 1214 // return an array of type FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS. Defaulting |
1189 PrintF(file, " from "); | 1215 // to FAST_ELEMENTS save the expense of element transition for code that |
1190 from_elements->ShortPrint(file); | 1216 // doesn't make use of double arrays. More FAST_ELEMENTS transitions than |
1191 PrintF(file, " to "); | 1217 // FAST_DOUBLE_ELEMENTS transitions suggest that Array() should always return |
1192 to_elements->ShortPrint(file); | 1218 // elements kinds of FAST_ELEMENTS. However, FAST_DOUBLE_ELEMENTS |
1193 PrintF(file, "\n"); | 1219 // transitions are weighted an order of magnitude heavier than FAST_ELEMENT |
1220 // transitions, since the savings is in general much greater if the runtime | |
1221 // can recognize and exploit FAST_DOUBLE_ELEMENTS, even at the expense of | |
1222 // extra transitions. | |
1223 Context* global_context = GetIsolate()->context()->global_context(); | |
1224 if (global_context->untransitioned_js_array_map() != NULL && | |
Jakob Kummerow
2012/01/04 20:55:17
Don't you mean s/NULL/GetHeap()->undefined_value()
| |
1225 IsJSArray() && from_kind == FAST_SMI_ONLY_ELEMENTS) { | |
1226 Object* bias_object = global_context->fast_array_element_bias(); | |
1227 if (!bias_object->IsUndefined()) { | |
1228 int bias = Smi::cast(bias_object)->value(); | |
1229 if (to_kind == FAST_ELEMENTS) { | |
1230 bias += kFastElementArrayBiasIncrement; | |
1231 } else { | |
1232 ASSERT(to_kind == FAST_DOUBLE_ELEMENTS); | |
1233 bias += kFastSmiOnlyElementArrayBiasIncrement; | |
1234 } | |
1235 global_context->set_fast_array_element_bias(Smi::FromInt(bias)); | |
1236 if (bias > kFastElementArrayBiasThreshold) { | |
1237 JSFunction* array_function = global_context->array_function(); | |
1238 Map* untransitioned_map = Map::cast( | |
1239 global_context->untransitioned_js_array_map()); | |
1240 if (untransitioned_map == array_function->initial_map()) { | |
1241 if (untransitioned_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS) { | |
1242 bool dummy; | |
1243 Map* transitioned_map = | |
1244 untransitioned_map->LookupElementsTransitionMap(FAST_ELEMENTS, | |
1245 &dummy); | |
Jakob Kummerow
2012/01/04 20:55:17
nit: indentation
| |
1246 if (transitioned_map != NULL) { | |
1247 array_function->set_initial_map(transitioned_map); | |
1248 } | |
1249 } | |
1250 } | |
1251 } else if (bias < kFastSmiOnlyElementArrayBiasThreshold) { | |
1252 JSFunction* array_function = global_context->array_function(); | |
1253 Map* untransitioned_map = Map::cast( | |
1254 global_context->untransitioned_js_array_map()); | |
1255 if (!untransitioned_map->IsUndefined() && | |
1256 untransitioned_map != array_function->initial_map()) { | |
1257 bool dummy; | |
1258 Map* transitioned_map = | |
1259 untransitioned_map->LookupElementsTransitionMap(FAST_ELEMENTS, | |
1260 &dummy); | |
1261 if (transitioned_map == array_function->initial_map()) { | |
1262 array_function->set_initial_map(untransitioned_map); | |
1263 } | |
1264 } | |
1265 } | |
1266 } | |
1194 } | 1267 } |
1195 } | 1268 } |
1196 | 1269 |
1197 | 1270 |
1198 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { | 1271 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { |
1199 Heap* heap = GetHeap(); | 1272 Heap* heap = GetHeap(); |
1200 if (!heap->Contains(this)) { | 1273 if (!heap->Contains(this)) { |
1201 accumulator->Add("!!!INVALID POINTER!!!"); | 1274 accumulator->Add("!!!INVALID POINTER!!!"); |
1202 return; | 1275 return; |
1203 } | 1276 } |
(...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2176 } else { | 2249 } else { |
2177 result->NotFound(); | 2250 result->NotFound(); |
2178 } | 2251 } |
2179 } | 2252 } |
2180 | 2253 |
2181 | 2254 |
2182 void Map::LookupInDescriptors(JSObject* holder, | 2255 void Map::LookupInDescriptors(JSObject* holder, |
2183 String* name, | 2256 String* name, |
2184 LookupResult* result) { | 2257 LookupResult* result) { |
2185 DescriptorArray* descriptors = instance_descriptors(); | 2258 DescriptorArray* descriptors = instance_descriptors(); |
2186 DescriptorLookupCache* cache = | 2259 int number = descriptors->SearchWithCache(name); |
2187 GetHeap()->isolate()->descriptor_lookup_cache(); | |
2188 int number = cache->Lookup(descriptors, name); | |
2189 if (number == DescriptorLookupCache::kAbsent) { | |
2190 number = descriptors->Search(name); | |
2191 cache->Update(descriptors, name, number); | |
2192 } | |
2193 if (number != DescriptorArray::kNotFound) { | 2260 if (number != DescriptorArray::kNotFound) { |
2194 result->DescriptorResult(holder, descriptors->GetDetails(number), number); | 2261 result->DescriptorResult(holder, descriptors->GetDetails(number), number); |
2195 } else { | 2262 } else { |
2196 result->NotFound(); | 2263 result->NotFound(); |
2197 } | 2264 } |
2198 } | 2265 } |
2199 | 2266 |
2200 | 2267 |
2201 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { | 2268 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { |
2202 ASSERT(!map.is_null()); | 2269 ASSERT(!map.is_null()); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2323 | 2390 |
2324 String* Map::elements_transition_sentinel_name() { | 2391 String* Map::elements_transition_sentinel_name() { |
2325 return GetHeap()->empty_symbol(); | 2392 return GetHeap()->empty_symbol(); |
2326 } | 2393 } |
2327 | 2394 |
2328 | 2395 |
2329 Object* Map::GetDescriptorContents(String* sentinel_name, | 2396 Object* Map::GetDescriptorContents(String* sentinel_name, |
2330 bool* safe_to_add_transition) { | 2397 bool* safe_to_add_transition) { |
2331 // Get the cached index for the descriptors lookup, or find and cache it. | 2398 // Get the cached index for the descriptors lookup, or find and cache it. |
2332 DescriptorArray* descriptors = instance_descriptors(); | 2399 DescriptorArray* descriptors = instance_descriptors(); |
2333 DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache(); | 2400 int index = descriptors->SearchWithCache(sentinel_name); |
2334 int index = cache->Lookup(descriptors, sentinel_name); | |
2335 if (index == DescriptorLookupCache::kAbsent) { | |
2336 index = descriptors->Search(sentinel_name); | |
2337 cache->Update(descriptors, sentinel_name, index); | |
2338 } | |
2339 // If the transition already exists, return its descriptor. | 2401 // If the transition already exists, return its descriptor. |
2340 if (index != DescriptorArray::kNotFound) { | 2402 if (index != DescriptorArray::kNotFound) { |
2341 PropertyDetails details(descriptors->GetDetails(index)); | 2403 PropertyDetails details(descriptors->GetDetails(index)); |
2342 if (details.type() == ELEMENTS_TRANSITION) { | 2404 if (details.type() == ELEMENTS_TRANSITION) { |
2343 return descriptors->GetValue(index); | 2405 return descriptors->GetValue(index); |
2344 } else { | 2406 } else { |
2345 *safe_to_add_transition = false; | 2407 *safe_to_add_transition = false; |
2346 } | 2408 } |
2347 } | 2409 } |
2348 return NULL; | 2410 return NULL; |
(...skipping 5924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8273 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8335 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
8274 case EXTERNAL_INT_ELEMENTS: | 8336 case EXTERNAL_INT_ELEMENTS: |
8275 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8337 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
8276 case EXTERNAL_FLOAT_ELEMENTS: | 8338 case EXTERNAL_FLOAT_ELEMENTS: |
8277 case EXTERNAL_DOUBLE_ELEMENTS: | 8339 case EXTERNAL_DOUBLE_ELEMENTS: |
8278 case EXTERNAL_PIXEL_ELEMENTS: | 8340 case EXTERNAL_PIXEL_ELEMENTS: |
8279 UNREACHABLE(); | 8341 UNREACHABLE(); |
8280 break; | 8342 break; |
8281 } | 8343 } |
8282 | 8344 |
8283 if (FLAG_trace_elements_transitions) { | 8345 RecordElementsTransition(elements_kind, old_elements_raw, |
8284 PrintElementsTransition(stdout, elements_kind, old_elements_raw, | 8346 FAST_ELEMENTS, new_elements); |
8285 FAST_ELEMENTS, new_elements); | |
8286 } | |
8287 | 8347 |
8288 // Update the length if necessary. | 8348 // Update the length if necessary. |
8289 if (IsJSArray()) { | 8349 if (IsJSArray()) { |
8290 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8350 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8291 } | 8351 } |
8292 | 8352 |
8293 return new_elements; | 8353 return new_elements; |
8294 } | 8354 } |
8295 | 8355 |
8296 | 8356 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8329 } | 8389 } |
8330 case DICTIONARY_ELEMENTS: { | 8390 case DICTIONARY_ELEMENTS: { |
8331 elems->Initialize(NumberDictionary::cast(old_elements)); | 8391 elems->Initialize(NumberDictionary::cast(old_elements)); |
8332 break; | 8392 break; |
8333 } | 8393 } |
8334 default: | 8394 default: |
8335 UNREACHABLE(); | 8395 UNREACHABLE(); |
8336 break; | 8396 break; |
8337 } | 8397 } |
8338 | 8398 |
8339 if (FLAG_trace_elements_transitions) { | 8399 RecordElementsTransition(elements_kind, old_elements, |
8340 PrintElementsTransition(stdout, elements_kind, old_elements, | 8400 FAST_DOUBLE_ELEMENTS, elems); |
8341 FAST_DOUBLE_ELEMENTS, elems); | |
8342 } | |
8343 | 8401 |
8344 ASSERT(new_map->has_fast_double_elements()); | 8402 ASSERT(new_map->has_fast_double_elements()); |
8345 set_map(new_map); | 8403 set_map(new_map); |
8346 ASSERT(elems->IsFixedDoubleArray()); | 8404 ASSERT(elems->IsFixedDoubleArray()); |
8347 set_elements(elems); | 8405 set_elements(elems); |
8348 | 8406 |
8349 if (IsJSArray()) { | 8407 if (IsJSArray()) { |
8350 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8408 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8351 } | 8409 } |
8352 | 8410 |
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9111 // Convert to fast double elements if appropriate. | 9169 // Convert to fast double elements if appropriate. |
9112 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { | 9170 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { |
9113 MaybeObject* maybe = | 9171 MaybeObject* maybe = |
9114 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 9172 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); |
9115 if (maybe->IsFailure()) return maybe; | 9173 if (maybe->IsFailure()) return maybe; |
9116 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 9174 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
9117 return value; | 9175 return value; |
9118 } | 9176 } |
9119 // Change elements kind from SMI_ONLY to generic FAST if necessary. | 9177 // Change elements kind from SMI_ONLY to generic FAST if necessary. |
9120 if (HasFastSmiOnlyElements() && !value->IsSmi()) { | 9178 if (HasFastSmiOnlyElements() && !value->IsSmi()) { |
9121 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); | 9179 MaybeObject* maybe = TransitionElementsKind(FAST_ELEMENTS); |
9122 Map* new_map; | 9180 if (maybe->IsFailure()) return maybe; |
9123 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | |
9124 set_map(new_map); | |
9125 if (FLAG_trace_elements_transitions) { | |
9126 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(), | |
9127 FAST_ELEMENTS, elements()); | |
9128 } | |
9129 } | 9181 } |
9130 // Increase backing store capacity if that's been decided previously. | 9182 // Increase backing store capacity if that's been decided previously. |
9131 if (new_capacity != capacity) { | 9183 if (new_capacity != capacity) { |
9132 Object* new_elements; | 9184 Object* new_elements; |
9133 SetFastElementsCapacityMode set_capacity_mode = | 9185 SetFastElementsCapacityMode set_capacity_mode = |
9134 value->IsSmi() && HasFastSmiOnlyElements() | 9186 value->IsSmi() && HasFastSmiOnlyElements() |
9135 ? kAllowSmiOnlyElements | 9187 ? kAllowSmiOnlyElements |
9136 : kDontAllowSmiOnlyElements; | 9188 : kDontAllowSmiOnlyElements; |
9137 MaybeObject* maybe = | 9189 MaybeObject* maybe = |
9138 SetFastElementsCapacityAndLength(new_capacity, | 9190 SetFastElementsCapacityAndLength(new_capacity, |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9487 // All possible cases have been handled above. Add a return to avoid the | 9539 // All possible cases have been handled above. Add a return to avoid the |
9488 // complaints from the compiler. | 9540 // complaints from the compiler. |
9489 UNREACHABLE(); | 9541 UNREACHABLE(); |
9490 return isolate->heap()->null_value(); | 9542 return isolate->heap()->null_value(); |
9491 } | 9543 } |
9492 | 9544 |
9493 | 9545 |
9494 MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( | 9546 MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( |
9495 ElementsKind to_kind) { | 9547 ElementsKind to_kind) { |
9496 ElementsKind from_kind = map()->elements_kind(); | 9548 ElementsKind from_kind = map()->elements_kind(); |
9549 if (from_kind == to_kind) return this; | |
9550 | |
9497 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9551 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9498 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 9552 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
9499 uint32_t length = capacity; | 9553 uint32_t length = capacity; |
9500 | 9554 |
9501 if (IsJSArray()) { | 9555 if (IsJSArray()) { |
9502 Object* raw_length = JSArray::cast(this)->length(); | 9556 Object* raw_length = JSArray::cast(this)->length(); |
9503 if (raw_length->IsUndefined()) { | 9557 if (raw_length->IsUndefined()) { |
9504 // If length is undefined, then JSArray is being initialized and has no | 9558 // If length is undefined, then JSArray is being initialized and has no |
9505 // elements, assume a length of zero. | 9559 // elements, assume a length of zero. |
9506 length = 0; | 9560 length = 0; |
9507 } else { | 9561 } else { |
9508 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9562 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
9509 } | 9563 } |
9510 } | 9564 } |
9511 | 9565 |
9512 if ((from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) || | 9566 if ((from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) || |
9513 (length == 0)) { | 9567 (length == 0)) { |
9514 MaybeObject* maybe_new_map = GetElementsTransitionMap(to_kind); | 9568 MaybeObject* maybe_new_map = GetElementsTransitionMap(to_kind); |
9515 Map* new_map; | 9569 Map* new_map; |
9516 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9570 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
9517 if (FLAG_trace_elements_transitions) { | 9571 RecordElementsTransition(from_kind, elms, to_kind, elms); |
9518 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | |
9519 } | |
9520 set_map(new_map); | 9572 set_map(new_map); |
9521 return this; | 9573 return this; |
9522 } | 9574 } |
9523 | 9575 |
9524 if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9576 if (from_kind == FAST_SMI_ONLY_ELEMENTS && |
9525 to_kind == FAST_DOUBLE_ELEMENTS) { | 9577 to_kind == FAST_DOUBLE_ELEMENTS) { |
9526 MaybeObject* maybe_result = | 9578 MaybeObject* maybe_result = |
9527 SetFastDoubleElementsCapacityAndLength(capacity, length); | 9579 SetFastDoubleElementsCapacityAndLength(capacity, length); |
9528 if (maybe_result->IsFailure()) return maybe_result; | 9580 if (maybe_result->IsFailure()) return maybe_result; |
9529 return this; | 9581 return this; |
(...skipping 3042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12572 if (break_point_objects()->IsUndefined()) return 0; | 12624 if (break_point_objects()->IsUndefined()) return 0; |
12573 // Single break point. | 12625 // Single break point. |
12574 if (!break_point_objects()->IsFixedArray()) return 1; | 12626 if (!break_point_objects()->IsFixedArray()) return 1; |
12575 // Multiple break points. | 12627 // Multiple break points. |
12576 return FixedArray::cast(break_point_objects())->length(); | 12628 return FixedArray::cast(break_point_objects())->length(); |
12577 } | 12629 } |
12578 #endif // ENABLE_DEBUGGER_SUPPORT | 12630 #endif // ENABLE_DEBUGGER_SUPPORT |
12579 | 12631 |
12580 | 12632 |
12581 } } // namespace v8::internal | 12633 } } // namespace v8::internal |
OLD | NEW |