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 2366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2377 Immediate(factory()->fixed_cow_array_map())); | 2377 Immediate(factory()->fixed_cow_array_map())); |
2378 __ j(equal, &done, Label::kNear); | 2378 __ j(equal, &done, Label::kNear); |
2379 Register temp((result.is(eax)) ? ebx : eax); | 2379 Register temp((result.is(eax)) ? ebx : eax); |
2380 __ push(temp); | 2380 __ push(temp); |
2381 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2381 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); |
2382 __ movzx_b(temp, FieldOperand(temp, Map::kBitField2Offset)); | 2382 __ movzx_b(temp, FieldOperand(temp, Map::kBitField2Offset)); |
2383 __ and_(temp, Map::kElementsKindMask); | 2383 __ and_(temp, Map::kElementsKindMask); |
2384 __ shr(temp, Map::kElementsKindShift); | 2384 __ shr(temp, Map::kElementsKindShift); |
2385 __ cmp(temp, FAST_ELEMENTS); | 2385 __ cmp(temp, FAST_ELEMENTS); |
2386 __ j(equal, &ok, Label::kNear); | 2386 __ j(equal, &ok, Label::kNear); |
| 2387 __ cmp(temp, FAST_HOLEY_ELEMENTS); |
| 2388 __ j(equal, &ok, Label::kNear); |
2387 __ cmp(temp, FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 2389 __ cmp(temp, FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
2388 __ j(less, &fail, Label::kNear); | 2390 __ j(less, &fail, Label::kNear); |
2389 __ cmp(temp, LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 2391 __ cmp(temp, LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
2390 __ j(less_equal, &ok, Label::kNear); | 2392 __ j(less_equal, &ok, Label::kNear); |
2391 __ bind(&fail); | 2393 __ bind(&fail); |
2392 __ Abort("Check for fast or external elements failed."); | 2394 __ Abort("Check for fast or external elements failed."); |
2393 __ bind(&ok); | 2395 __ bind(&ok); |
2394 __ pop(temp); | 2396 __ pop(temp); |
2395 __ bind(&done); | 2397 __ bind(&done); |
2396 } | 2398 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2435 __ cmp(result, factory()->the_hole_value()); | 2437 __ cmp(result, factory()->the_hole_value()); |
2436 DeoptimizeIf(equal, instr->environment()); | 2438 DeoptimizeIf(equal, instr->environment()); |
2437 } | 2439 } |
2438 } | 2440 } |
2439 | 2441 |
2440 | 2442 |
2441 void LCodeGen::DoLoadKeyedFastDoubleElement( | 2443 void LCodeGen::DoLoadKeyedFastDoubleElement( |
2442 LLoadKeyedFastDoubleElement* instr) { | 2444 LLoadKeyedFastDoubleElement* instr) { |
2443 XMMRegister result = ToDoubleRegister(instr->result()); | 2445 XMMRegister result = ToDoubleRegister(instr->result()); |
2444 | 2446 |
2445 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | 2447 if (instr->hydrogen()->RequiresHoleCheck()) { |
2446 sizeof(kHoleNanLower32); | 2448 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
2447 Operand hole_check_operand = BuildFastArrayOperand( | 2449 sizeof(kHoleNanLower32); |
2448 instr->elements(), instr->key(), | 2450 Operand hole_check_operand = BuildFastArrayOperand( |
2449 FAST_DOUBLE_ELEMENTS, | 2451 instr->elements(), instr->key(), |
2450 offset); | 2452 FAST_DOUBLE_ELEMENTS, |
2451 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); | 2453 offset); |
2452 DeoptimizeIf(equal, instr->environment()); | 2454 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 2455 DeoptimizeIf(equal, instr->environment()); |
| 2456 } |
2453 | 2457 |
2454 Operand double_load_operand = BuildFastArrayOperand( | 2458 Operand double_load_operand = BuildFastArrayOperand( |
2455 instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, | 2459 instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, |
2456 FixedDoubleArray::kHeaderSize - kHeapObjectTag); | 2460 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
2457 __ movdbl(result, double_load_operand); | 2461 __ movdbl(result, double_load_operand); |
2458 } | 2462 } |
2459 | 2463 |
2460 | 2464 |
2461 Operand LCodeGen::BuildFastArrayOperand( | 2465 Operand LCodeGen::BuildFastArrayOperand( |
2462 LOperand* elements_pointer, | 2466 LOperand* elements_pointer, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2512 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2516 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
2513 __ mov(result, operand); | 2517 __ mov(result, operand); |
2514 __ test(result, Operand(result)); | 2518 __ test(result, Operand(result)); |
2515 // TODO(danno): we could be more clever here, perhaps having a special | 2519 // TODO(danno): we could be more clever here, perhaps having a special |
2516 // version of the stub that detects if the overflow case actually | 2520 // version of the stub that detects if the overflow case actually |
2517 // happens, and generate code that returns a double rather than int. | 2521 // happens, and generate code that returns a double rather than int. |
2518 DeoptimizeIf(negative, instr->environment()); | 2522 DeoptimizeIf(negative, instr->environment()); |
2519 break; | 2523 break; |
2520 case EXTERNAL_FLOAT_ELEMENTS: | 2524 case EXTERNAL_FLOAT_ELEMENTS: |
2521 case EXTERNAL_DOUBLE_ELEMENTS: | 2525 case EXTERNAL_DOUBLE_ELEMENTS: |
2522 case FAST_SMI_ONLY_ELEMENTS: | 2526 case FAST_SMI_ELEMENTS: |
2523 case FAST_ELEMENTS: | 2527 case FAST_ELEMENTS: |
2524 case FAST_DOUBLE_ELEMENTS: | 2528 case FAST_DOUBLE_ELEMENTS: |
| 2529 case FAST_HOLEY_SMI_ELEMENTS: |
| 2530 case FAST_HOLEY_ELEMENTS: |
| 2531 case FAST_HOLEY_DOUBLE_ELEMENTS: |
2525 case DICTIONARY_ELEMENTS: | 2532 case DICTIONARY_ELEMENTS: |
2526 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2533 case NON_STRICT_ARGUMENTS_ELEMENTS: |
2527 UNREACHABLE(); | 2534 UNREACHABLE(); |
2528 break; | 2535 break; |
2529 } | 2536 } |
2530 } | 2537 } |
2531 } | 2538 } |
2532 | 2539 |
2533 | 2540 |
2534 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2541 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3437 case EXTERNAL_SHORT_ELEMENTS: | 3444 case EXTERNAL_SHORT_ELEMENTS: |
3438 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3445 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3439 __ mov_w(operand, value); | 3446 __ mov_w(operand, value); |
3440 break; | 3447 break; |
3441 case EXTERNAL_INT_ELEMENTS: | 3448 case EXTERNAL_INT_ELEMENTS: |
3442 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3449 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3443 __ mov(operand, value); | 3450 __ mov(operand, value); |
3444 break; | 3451 break; |
3445 case EXTERNAL_FLOAT_ELEMENTS: | 3452 case EXTERNAL_FLOAT_ELEMENTS: |
3446 case EXTERNAL_DOUBLE_ELEMENTS: | 3453 case EXTERNAL_DOUBLE_ELEMENTS: |
3447 case FAST_SMI_ONLY_ELEMENTS: | 3454 case FAST_SMI_ELEMENTS: |
3448 case FAST_ELEMENTS: | 3455 case FAST_ELEMENTS: |
3449 case FAST_DOUBLE_ELEMENTS: | 3456 case FAST_DOUBLE_ELEMENTS: |
| 3457 case FAST_HOLEY_SMI_ELEMENTS: |
| 3458 case FAST_HOLEY_ELEMENTS: |
| 3459 case FAST_HOLEY_DOUBLE_ELEMENTS: |
3450 case DICTIONARY_ELEMENTS: | 3460 case DICTIONARY_ELEMENTS: |
3451 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3461 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3452 UNREACHABLE(); | 3462 UNREACHABLE(); |
3453 break; | 3463 break; |
3454 } | 3464 } |
3455 } | 3465 } |
3456 } | 3466 } |
3457 | 3467 |
3458 | 3468 |
3459 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3469 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3517 FixedDoubleArray::kHeaderSize - kHeapObjectTag); | 3527 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
3518 __ movdbl(double_store_operand, value); | 3528 __ movdbl(double_store_operand, value); |
3519 } | 3529 } |
3520 | 3530 |
3521 | 3531 |
3522 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3532 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
3523 ASSERT(ToRegister(instr->context()).is(esi)); | 3533 ASSERT(ToRegister(instr->context()).is(esi)); |
3524 ASSERT(ToRegister(instr->object()).is(edx)); | 3534 ASSERT(ToRegister(instr->object()).is(edx)); |
3525 ASSERT(ToRegister(instr->key()).is(ecx)); | 3535 ASSERT(ToRegister(instr->key()).is(ecx)); |
3526 ASSERT(ToRegister(instr->value()).is(eax)); | 3536 ASSERT(ToRegister(instr->value()).is(eax)); |
3527 | |
3528 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3537 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3529 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3538 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3530 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3539 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3531 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3540 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3532 } | 3541 } |
3533 | 3542 |
3534 | 3543 |
3535 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 3544 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
3536 Register object_reg = ToRegister(instr->object()); | 3545 Register object_reg = ToRegister(instr->object()); |
3537 Register new_map_reg = ToRegister(instr->new_map_reg()); | 3546 Register new_map_reg = ToRegister(instr->new_map_reg()); |
3538 | 3547 |
3539 Handle<Map> from_map = instr->original_map(); | 3548 Handle<Map> from_map = instr->original_map(); |
3540 Handle<Map> to_map = instr->transitioned_map(); | 3549 Handle<Map> to_map = instr->transitioned_map(); |
3541 ElementsKind from_kind = from_map->elements_kind(); | 3550 ElementsKind from_kind = from_map->elements_kind(); |
3542 ElementsKind to_kind = to_map->elements_kind(); | 3551 ElementsKind to_kind = to_map->elements_kind(); |
3543 | 3552 |
3544 Label not_applicable; | 3553 Label not_applicable; |
3545 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3554 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
3546 __ j(not_equal, ¬_applicable); | 3555 __ j(not_equal, ¬_applicable); |
3547 __ mov(new_map_reg, to_map); | 3556 __ mov(new_map_reg, to_map); |
3548 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3557 bool simple_map_change = (GetHoleyElementsKind(from_kind) == to_kind) || |
| 3558 (IsFastSmiElementsKind(from_kind) && |
| 3559 IsFastObjectElementsKind(to_kind)); |
| 3560 if (simple_map_change) { |
3549 Register object_reg = ToRegister(instr->object()); | 3561 Register object_reg = ToRegister(instr->object()); |
3550 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3562 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
3551 // Write barrier. | 3563 // Write barrier. |
3552 ASSERT_NE(instr->temp_reg(), NULL); | 3564 ASSERT_NE(instr->temp_reg(), NULL); |
3553 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3565 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
3554 ToRegister(instr->temp_reg()), kDontSaveFPRegs); | 3566 ToRegister(instr->temp_reg()), kDontSaveFPRegs); |
3555 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 3567 } else if (IsFastSmiElementsKind(from_kind) && |
3556 to_kind == FAST_DOUBLE_ELEMENTS) { | 3568 IsFastDoubleElementsKind(to_kind)) { |
3557 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3569 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3558 ASSERT(fixed_object_reg.is(edx)); | 3570 ASSERT(fixed_object_reg.is(edx)); |
3559 ASSERT(new_map_reg.is(ebx)); | 3571 ASSERT(new_map_reg.is(ebx)); |
3560 __ mov(fixed_object_reg, object_reg); | 3572 __ mov(fixed_object_reg, object_reg); |
3561 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3573 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
3562 RelocInfo::CODE_TARGET, instr); | 3574 RelocInfo::CODE_TARGET, instr); |
3563 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3575 } else if (IsFastDoubleElementsKind(from_kind) && |
| 3576 IsFastElementsKind(to_kind)) { |
3564 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3577 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3565 ASSERT(fixed_object_reg.is(edx)); | 3578 ASSERT(fixed_object_reg.is(edx)); |
3566 ASSERT(new_map_reg.is(ebx)); | 3579 ASSERT(new_map_reg.is(ebx)); |
3567 __ mov(fixed_object_reg, object_reg); | 3580 __ mov(fixed_object_reg, object_reg); |
3568 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3581 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
3569 RelocInfo::CODE_TARGET, instr); | 3582 RelocInfo::CODE_TARGET, instr); |
3570 } else { | 3583 } else { |
3571 UNREACHABLE(); | 3584 UNREACHABLE(); |
3572 } | 3585 } |
3573 __ bind(¬_applicable); | 3586 __ bind(¬_applicable); |
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4413 | 4426 |
4414 | 4427 |
4415 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4428 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
4416 ASSERT(ToRegister(instr->context()).is(esi)); | 4429 ASSERT(ToRegister(instr->context()).is(esi)); |
4417 Heap* heap = isolate()->heap(); | 4430 Heap* heap = isolate()->heap(); |
4418 ElementsKind boilerplate_elements_kind = | 4431 ElementsKind boilerplate_elements_kind = |
4419 instr->hydrogen()->boilerplate_elements_kind(); | 4432 instr->hydrogen()->boilerplate_elements_kind(); |
4420 | 4433 |
4421 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4434 // Deopt if the array literal boilerplate ElementsKind is of a type different |
4422 // than the expected one. The check isn't necessary if the boilerplate has | 4435 // than the expected one. The check isn't necessary if the boilerplate has |
4423 // already been converted to FAST_ELEMENTS. | 4436 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. |
4424 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4437 if (CanTransitionToMoreGeneralFastElementsKind( |
| 4438 boilerplate_elements_kind, true)) { |
4425 __ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object()); | 4439 __ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object()); |
4426 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 4440 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
4427 // Load the map's "bit field 2". We only need the first byte, | 4441 // Load the map's "bit field 2". We only need the first byte, |
4428 // but the following masking takes care of that anyway. | 4442 // but the following masking takes care of that anyway. |
4429 __ mov(ebx, FieldOperand(ebx, Map::kBitField2Offset)); | 4443 __ mov(ebx, FieldOperand(ebx, Map::kBitField2Offset)); |
4430 // Retrieve elements_kind from bit field 2. | 4444 // Retrieve elements_kind from bit field 2. |
4431 __ and_(ebx, Map::kElementsKindMask); | 4445 __ and_(ebx, Map::kElementsKindMask); |
4432 __ cmp(ebx, boilerplate_elements_kind << Map::kElementsKindShift); | 4446 __ cmp(ebx, boilerplate_elements_kind << Map::kElementsKindShift); |
4433 DeoptimizeIf(not_equal, instr->environment()); | 4447 DeoptimizeIf(not_equal, instr->environment()); |
4434 } | 4448 } |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5062 FixedArray::kHeaderSize - kPointerSize)); | 5076 FixedArray::kHeaderSize - kPointerSize)); |
5063 __ bind(&done); | 5077 __ bind(&done); |
5064 } | 5078 } |
5065 | 5079 |
5066 | 5080 |
5067 #undef __ | 5081 #undef __ |
5068 | 5082 |
5069 } } // namespace v8::internal | 5083 } } // namespace v8::internal |
5070 | 5084 |
5071 #endif // V8_TARGET_ARCH_IA32 | 5085 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |