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 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 // constant function properties. | 421 // constant function properties. |
422 if (should_transform && !has_function_literal) { | 422 if (should_transform && !has_function_literal) { |
423 JSObject::TransformToFastProperties( | 423 JSObject::TransformToFastProperties( |
424 boilerplate, boilerplate->map()->unused_property_fields()); | 424 boilerplate, boilerplate->map()->unused_property_fields()); |
425 } | 425 } |
426 | 426 |
427 return boilerplate; | 427 return boilerplate; |
428 } | 428 } |
429 | 429 |
430 | 430 |
| 431 MaybeObject* TransitionElements(Handle<Object> object, |
| 432 ElementsKind to_kind, |
| 433 Isolate* isolate) { |
| 434 HandleScope scope(isolate); |
| 435 if (!object->IsJSObject()) return isolate->ThrowIllegalOperation(); |
| 436 ElementsKind from_kind = |
| 437 Handle<JSObject>::cast(object)->map()->elements_kind(); |
| 438 if (Map::IsValidElementsTransition(from_kind, to_kind)) { |
| 439 Handle<Object> result = JSObject::TransitionElementsKind( |
| 440 Handle<JSObject>::cast(object), to_kind); |
| 441 if (result.is_null()) return isolate->ThrowIllegalOperation(); |
| 442 return *result; |
| 443 } |
| 444 return isolate->ThrowIllegalOperation(); |
| 445 } |
| 446 |
| 447 |
431 static const int kSmiOnlyLiteralMinimumLength = 1024; | 448 static const int kSmiOnlyLiteralMinimumLength = 1024; |
432 | 449 |
433 | 450 |
434 Handle<Object> Runtime::CreateArrayLiteralBoilerplate( | 451 Handle<Object> Runtime::CreateArrayLiteralBoilerplate( |
435 Isolate* isolate, | 452 Isolate* isolate, |
436 Handle<FixedArray> literals, | 453 Handle<FixedArray> literals, |
437 Handle<FixedArray> elements) { | 454 Handle<FixedArray> elements) { |
438 // Create the JSArray. | 455 // Create the JSArray. |
439 Handle<JSFunction> constructor( | 456 Handle<JSFunction> constructor( |
440 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); | 457 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); |
441 Handle<JSArray> object = | 458 Handle<JSArray> object = |
442 Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor)); | 459 Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor)); |
443 | 460 |
444 ElementsKind constant_elements_kind = | 461 ElementsKind constant_elements_kind = |
445 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); | 462 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); |
446 Handle<FixedArrayBase> constant_elements_values( | 463 Handle<FixedArrayBase> constant_elements_values( |
447 FixedArrayBase::cast(elements->get(1))); | 464 FixedArrayBase::cast(elements->get(1))); |
448 | 465 |
449 ASSERT(FLAG_smi_only_arrays || constant_elements_kind == FAST_ELEMENTS || | 466 Context* global_context = isolate->context()->global_context(); |
450 constant_elements_kind == FAST_SMI_ONLY_ELEMENTS); | 467 if (constant_elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
451 bool allow_literal_kind_transition = FLAG_smi_only_arrays && | 468 object->set_map(Map::cast(global_context->smi_js_array_map())); |
452 constant_elements_kind > object->GetElementsKind(); | 469 } else if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) { |
453 | 470 object->set_map(Map::cast(global_context->double_js_array_map())); |
454 if (!FLAG_smi_only_arrays && | 471 } else { |
455 constant_elements_values->length() > kSmiOnlyLiteralMinimumLength && | 472 object->set_map(Map::cast(global_context->object_js_array_map())); |
456 constant_elements_kind != object->GetElementsKind()) { | |
457 allow_literal_kind_transition = true; | |
458 } | |
459 | |
460 // If the ElementsKind of the constant values of the array literal are less | |
461 // specific than the ElementsKind of the boilerplate array object, change the | |
462 // boilerplate array object's map to reflect that kind. | |
463 if (allow_literal_kind_transition) { | |
464 Handle<Map> transitioned_array_map = | |
465 isolate->factory()->GetElementsTransitionMap(object, | |
466 constant_elements_kind); | |
467 object->set_map(*transitioned_array_map); | |
468 } | 473 } |
469 | 474 |
470 Handle<FixedArrayBase> copied_elements_values; | 475 Handle<FixedArrayBase> copied_elements_values; |
471 if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) { | 476 if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) { |
472 ASSERT(FLAG_smi_only_arrays); | 477 ASSERT(FLAG_smi_only_arrays); |
473 copied_elements_values = isolate->factory()->CopyFixedDoubleArray( | 478 copied_elements_values = isolate->factory()->CopyFixedDoubleArray( |
474 Handle<FixedDoubleArray>::cast(constant_elements_values)); | 479 Handle<FixedDoubleArray>::cast(constant_elements_values)); |
475 } else { | 480 } else { |
476 ASSERT(constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || | 481 ASSERT(constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || |
477 constant_elements_kind == FAST_ELEMENTS); | 482 constant_elements_kind == FAST_ELEMENTS); |
(...skipping 24 matching lines...) Expand all Loading... |
502 Handle<Object> result = | 507 Handle<Object> result = |
503 CreateLiteralBoilerplate(isolate, literals, fa); | 508 CreateLiteralBoilerplate(isolate, literals, fa); |
504 if (result.is_null()) return result; | 509 if (result.is_null()) return result; |
505 fixed_array_values_copy->set(i, *result); | 510 fixed_array_values_copy->set(i, *result); |
506 } | 511 } |
507 } | 512 } |
508 } | 513 } |
509 } | 514 } |
510 object->set_elements(*copied_elements_values); | 515 object->set_elements(*copied_elements_values); |
511 object->set_length(Smi::FromInt(copied_elements_values->length())); | 516 object->set_length(Smi::FromInt(copied_elements_values->length())); |
| 517 |
| 518 // Ensure that the boilerplate object has FAST_ELEMENTS, unless the flag is |
| 519 // on or the object is larger than the threshold. |
| 520 if (!FLAG_smi_only_arrays && |
| 521 constant_elements_values->length() < kSmiOnlyLiteralMinimumLength) { |
| 522 if (object->GetElementsKind() != FAST_ELEMENTS) { |
| 523 CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure()); |
| 524 } |
| 525 } |
| 526 |
512 return object; | 527 return object; |
513 } | 528 } |
514 | 529 |
515 | 530 |
516 static Handle<Object> CreateLiteralBoilerplate( | 531 static Handle<Object> CreateLiteralBoilerplate( |
517 Isolate* isolate, | 532 Isolate* isolate, |
518 Handle<FixedArray> literals, | 533 Handle<FixedArray> literals, |
519 Handle<FixedArray> array) { | 534 Handle<FixedArray> array) { |
520 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); | 535 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); |
521 const bool kHasNoFunctionLiteral = false; | 536 const bool kHasNoFunctionLiteral = false; |
(...skipping 3673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4195 NoHandleAllocation ha; | 4210 NoHandleAllocation ha; |
4196 ASSERT(args.length() == 2); | 4211 ASSERT(args.length() == 2); |
4197 | 4212 |
4198 Handle<Object> object = args.at<Object>(0); | 4213 Handle<Object> object = args.at<Object>(0); |
4199 Handle<Object> key = args.at<Object>(1); | 4214 Handle<Object> key = args.at<Object>(1); |
4200 | 4215 |
4201 return Runtime::GetObjectProperty(isolate, object, key); | 4216 return Runtime::GetObjectProperty(isolate, object, key); |
4202 } | 4217 } |
4203 | 4218 |
4204 | 4219 |
4205 MaybeObject* TransitionElements(Handle<Object> object, | |
4206 ElementsKind to_kind, | |
4207 Isolate* isolate) { | |
4208 HandleScope scope(isolate); | |
4209 if (!object->IsJSObject()) return isolate->ThrowIllegalOperation(); | |
4210 ElementsKind from_kind = | |
4211 Handle<JSObject>::cast(object)->map()->elements_kind(); | |
4212 if (Map::IsValidElementsTransition(from_kind, to_kind)) { | |
4213 Handle<Object> result = JSObject::TransitionElementsKind( | |
4214 Handle<JSObject>::cast(object), to_kind); | |
4215 if (result.is_null()) return isolate->ThrowIllegalOperation(); | |
4216 return *result; | |
4217 } | |
4218 return isolate->ThrowIllegalOperation(); | |
4219 } | |
4220 | |
4221 | |
4222 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric. | 4220 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric. |
4223 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { | 4221 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { |
4224 NoHandleAllocation ha; | 4222 NoHandleAllocation ha; |
4225 ASSERT(args.length() == 2); | 4223 ASSERT(args.length() == 2); |
4226 | 4224 |
4227 // Fast cases for getting named properties of the receiver JSObject | 4225 // Fast cases for getting named properties of the receiver JSObject |
4228 // itself. | 4226 // itself. |
4229 // | 4227 // |
4230 // The global proxy objects has to be excluded since LocalLookup on | 4228 // The global proxy objects has to be excluded since LocalLookup on |
4231 // the global proxy object can return a valid result even though the | 4229 // the global proxy object can return a valid result even though the |
(...skipping 5992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10224 ElementsKind elements_kind; | 10222 ElementsKind elements_kind; |
10225 if (new_elements->map() == isolate->heap()->fixed_array_map() || | 10223 if (new_elements->map() == isolate->heap()->fixed_array_map() || |
10226 new_elements->map() == isolate->heap()->fixed_cow_array_map()) { | 10224 new_elements->map() == isolate->heap()->fixed_cow_array_map()) { |
10227 elements_kind = FAST_ELEMENTS; | 10225 elements_kind = FAST_ELEMENTS; |
10228 } else if (new_elements->map() == | 10226 } else if (new_elements->map() == |
10229 isolate->heap()->fixed_double_array_map()) { | 10227 isolate->heap()->fixed_double_array_map()) { |
10230 elements_kind = FAST_DOUBLE_ELEMENTS; | 10228 elements_kind = FAST_DOUBLE_ELEMENTS; |
10231 } else { | 10229 } else { |
10232 elements_kind = DICTIONARY_ELEMENTS; | 10230 elements_kind = DICTIONARY_ELEMENTS; |
10233 } | 10231 } |
10234 maybe_new_map = to->GetElementsTransitionMap(elements_kind); | 10232 maybe_new_map = to->GetElementsTransitionMap(isolate, elements_kind); |
10235 Object* new_map; | 10233 Object* new_map; |
10236 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 10234 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
10237 to->set_map(Map::cast(new_map)); | 10235 to->set_map(Map::cast(new_map)); |
10238 to->set_elements(new_elements); | 10236 to->set_elements(new_elements); |
10239 to->set_length(from->length()); | 10237 to->set_length(from->length()); |
10240 Object* obj; | 10238 Object* obj; |
10241 { MaybeObject* maybe_obj = from->ResetElements(); | 10239 { MaybeObject* maybe_obj = from->ResetElements(); |
10242 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 10240 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
10243 } | 10241 } |
10244 from->set_length(Smi::FromInt(0)); | 10242 from->set_length(Smi::FromInt(0)); |
(...skipping 3390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13635 } else { | 13633 } else { |
13636 // Handle last resort GC and make sure to allow future allocations | 13634 // Handle last resort GC and make sure to allow future allocations |
13637 // to grow the heap without causing GCs (if possible). | 13635 // to grow the heap without causing GCs (if possible). |
13638 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13636 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13639 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 13637 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
13640 } | 13638 } |
13641 } | 13639 } |
13642 | 13640 |
13643 | 13641 |
13644 } } // namespace v8::internal | 13642 } } // namespace v8::internal |
OLD | NEW |