| 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 2365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2376 Immediate(factory()->fixed_cow_array_map())); | 2376 Immediate(factory()->fixed_cow_array_map())); |
| 2377 __ j(equal, &done, Label::kNear); | 2377 __ j(equal, &done, Label::kNear); |
| 2378 Register temp((result.is(eax)) ? ebx : eax); | 2378 Register temp((result.is(eax)) ? ebx : eax); |
| 2379 __ push(temp); | 2379 __ push(temp); |
| 2380 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2380 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); |
| 2381 __ movzx_b(temp, FieldOperand(temp, Map::kBitField2Offset)); | 2381 __ movzx_b(temp, FieldOperand(temp, Map::kBitField2Offset)); |
| 2382 __ and_(temp, Map::kElementsKindMask); | 2382 __ and_(temp, Map::kElementsKindMask); |
| 2383 __ shr(temp, Map::kElementsKindShift); | 2383 __ shr(temp, Map::kElementsKindShift); |
| 2384 __ cmp(temp, FAST_ELEMENTS); | 2384 __ cmp(temp, FAST_ELEMENTS); |
| 2385 __ j(equal, &ok, Label::kNear); | 2385 __ j(equal, &ok, Label::kNear); |
| 2386 __ cmp(temp, FAST_HOLEY_ELEMENTS); |
| 2387 __ j(equal, &ok, Label::kNear); |
| 2386 __ cmp(temp, FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 2388 __ cmp(temp, FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
| 2387 __ j(less, &fail, Label::kNear); | 2389 __ j(less, &fail, Label::kNear); |
| 2388 __ cmp(temp, LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 2390 __ cmp(temp, LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); |
| 2389 __ j(less_equal, &ok, Label::kNear); | 2391 __ j(less_equal, &ok, Label::kNear); |
| 2390 __ bind(&fail); | 2392 __ bind(&fail); |
| 2391 __ Abort("Check for fast or external elements failed."); | 2393 __ Abort("Check for fast or external elements failed."); |
| 2392 __ bind(&ok); | 2394 __ bind(&ok); |
| 2393 __ pop(temp); | 2395 __ pop(temp); |
| 2394 __ bind(&done); | 2396 __ bind(&done); |
| 2395 } | 2397 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2434 __ cmp(result, factory()->the_hole_value()); | 2436 __ cmp(result, factory()->the_hole_value()); |
| 2435 DeoptimizeIf(equal, instr->environment()); | 2437 DeoptimizeIf(equal, instr->environment()); |
| 2436 } | 2438 } |
| 2437 } | 2439 } |
| 2438 | 2440 |
| 2439 | 2441 |
| 2440 void LCodeGen::DoLoadKeyedFastDoubleElement( | 2442 void LCodeGen::DoLoadKeyedFastDoubleElement( |
| 2441 LLoadKeyedFastDoubleElement* instr) { | 2443 LLoadKeyedFastDoubleElement* instr) { |
| 2442 XMMRegister result = ToDoubleRegister(instr->result()); | 2444 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2443 | 2445 |
| 2444 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | 2446 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2445 sizeof(kHoleNanLower32); | 2447 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
| 2446 Operand hole_check_operand = BuildFastArrayOperand( | 2448 sizeof(kHoleNanLower32); |
| 2447 instr->elements(), instr->key(), | 2449 Operand hole_check_operand = BuildFastArrayOperand( |
| 2448 FAST_DOUBLE_ELEMENTS, | 2450 instr->elements(), instr->key(), |
| 2449 offset); | 2451 FAST_DOUBLE_ELEMENTS, |
| 2450 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); | 2452 offset); |
| 2451 DeoptimizeIf(equal, instr->environment()); | 2453 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 2454 DeoptimizeIf(equal, instr->environment()); |
| 2455 } |
| 2452 | 2456 |
| 2453 Operand double_load_operand = BuildFastArrayOperand( | 2457 Operand double_load_operand = BuildFastArrayOperand( |
| 2454 instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, | 2458 instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, |
| 2455 FixedDoubleArray::kHeaderSize - kHeapObjectTag); | 2459 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
| 2456 __ movdbl(result, double_load_operand); | 2460 __ movdbl(result, double_load_operand); |
| 2457 } | 2461 } |
| 2458 | 2462 |
| 2459 | 2463 |
| 2460 Operand LCodeGen::BuildFastArrayOperand( | 2464 Operand LCodeGen::BuildFastArrayOperand( |
| 2461 LOperand* elements_pointer, | 2465 LOperand* elements_pointer, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2511 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2515 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 2512 __ mov(result, operand); | 2516 __ mov(result, operand); |
| 2513 __ test(result, Operand(result)); | 2517 __ test(result, Operand(result)); |
| 2514 // TODO(danno): we could be more clever here, perhaps having a special | 2518 // TODO(danno): we could be more clever here, perhaps having a special |
| 2515 // version of the stub that detects if the overflow case actually | 2519 // version of the stub that detects if the overflow case actually |
| 2516 // happens, and generate code that returns a double rather than int. | 2520 // happens, and generate code that returns a double rather than int. |
| 2517 DeoptimizeIf(negative, instr->environment()); | 2521 DeoptimizeIf(negative, instr->environment()); |
| 2518 break; | 2522 break; |
| 2519 case EXTERNAL_FLOAT_ELEMENTS: | 2523 case EXTERNAL_FLOAT_ELEMENTS: |
| 2520 case EXTERNAL_DOUBLE_ELEMENTS: | 2524 case EXTERNAL_DOUBLE_ELEMENTS: |
| 2521 case FAST_SMI_ONLY_ELEMENTS: | 2525 case FAST_SMI_ELEMENTS: |
| 2522 case FAST_ELEMENTS: | 2526 case FAST_ELEMENTS: |
| 2523 case FAST_DOUBLE_ELEMENTS: | 2527 case FAST_DOUBLE_ELEMENTS: |
| 2528 case FAST_HOLEY_SMI_ELEMENTS: |
| 2529 case FAST_HOLEY_ELEMENTS: |
| 2530 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 2524 case DICTIONARY_ELEMENTS: | 2531 case DICTIONARY_ELEMENTS: |
| 2525 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2532 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 2526 UNREACHABLE(); | 2533 UNREACHABLE(); |
| 2527 break; | 2534 break; |
| 2528 } | 2535 } |
| 2529 } | 2536 } |
| 2530 } | 2537 } |
| 2531 | 2538 |
| 2532 | 2539 |
| 2533 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2540 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| (...skipping 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3424 case EXTERNAL_SHORT_ELEMENTS: | 3431 case EXTERNAL_SHORT_ELEMENTS: |
| 3425 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3432 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3426 __ mov_w(operand, value); | 3433 __ mov_w(operand, value); |
| 3427 break; | 3434 break; |
| 3428 case EXTERNAL_INT_ELEMENTS: | 3435 case EXTERNAL_INT_ELEMENTS: |
| 3429 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3436 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3430 __ mov(operand, value); | 3437 __ mov(operand, value); |
| 3431 break; | 3438 break; |
| 3432 case EXTERNAL_FLOAT_ELEMENTS: | 3439 case EXTERNAL_FLOAT_ELEMENTS: |
| 3433 case EXTERNAL_DOUBLE_ELEMENTS: | 3440 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3434 case FAST_SMI_ONLY_ELEMENTS: | 3441 case FAST_SMI_ELEMENTS: |
| 3435 case FAST_ELEMENTS: | 3442 case FAST_ELEMENTS: |
| 3436 case FAST_DOUBLE_ELEMENTS: | 3443 case FAST_DOUBLE_ELEMENTS: |
| 3444 case FAST_HOLEY_SMI_ELEMENTS: |
| 3445 case FAST_HOLEY_ELEMENTS: |
| 3446 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3437 case DICTIONARY_ELEMENTS: | 3447 case DICTIONARY_ELEMENTS: |
| 3438 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3448 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3439 UNREACHABLE(); | 3449 UNREACHABLE(); |
| 3440 break; | 3450 break; |
| 3441 } | 3451 } |
| 3442 } | 3452 } |
| 3443 } | 3453 } |
| 3444 | 3454 |
| 3445 | 3455 |
| 3446 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3456 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3504 FixedDoubleArray::kHeaderSize - kHeapObjectTag); | 3514 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
| 3505 __ movdbl(double_store_operand, value); | 3515 __ movdbl(double_store_operand, value); |
| 3506 } | 3516 } |
| 3507 | 3517 |
| 3508 | 3518 |
| 3509 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3519 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 3510 ASSERT(ToRegister(instr->context()).is(esi)); | 3520 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3511 ASSERT(ToRegister(instr->object()).is(edx)); | 3521 ASSERT(ToRegister(instr->object()).is(edx)); |
| 3512 ASSERT(ToRegister(instr->key()).is(ecx)); | 3522 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 3513 ASSERT(ToRegister(instr->value()).is(eax)); | 3523 ASSERT(ToRegister(instr->value()).is(eax)); |
| 3514 | |
| 3515 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3524 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 3516 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3525 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3517 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3526 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3518 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3527 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3519 } | 3528 } |
| 3520 | 3529 |
| 3521 | 3530 |
| 3522 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 3531 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 3523 Register object_reg = ToRegister(instr->object()); | 3532 Register object_reg = ToRegister(instr->object()); |
| 3524 Register new_map_reg = ToRegister(instr->new_map_reg()); | 3533 Register new_map_reg = ToRegister(instr->new_map_reg()); |
| 3525 | 3534 |
| 3526 Handle<Map> from_map = instr->original_map(); | 3535 Handle<Map> from_map = instr->original_map(); |
| 3527 Handle<Map> to_map = instr->transitioned_map(); | 3536 Handle<Map> to_map = instr->transitioned_map(); |
| 3528 ElementsKind from_kind = from_map->elements_kind(); | 3537 ElementsKind from_kind = from_map->elements_kind(); |
| 3529 ElementsKind to_kind = to_map->elements_kind(); | 3538 ElementsKind to_kind = to_map->elements_kind(); |
| 3530 | 3539 |
| 3531 Label not_applicable; | 3540 Label not_applicable; |
| 3532 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3541 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
| 3533 __ j(not_equal, ¬_applicable); | 3542 __ j(not_equal, ¬_applicable); |
| 3534 __ mov(new_map_reg, to_map); | 3543 __ mov(new_map_reg, to_map); |
| 3535 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3544 bool simple_map_change = (GetHoleyElementsKind(from_kind) == to_kind) || |
| 3545 (IsFastSmiElementsKind(from_kind) && |
| 3546 IsFastObjectElementsKind(to_kind)); |
| 3547 if (simple_map_change) { |
| 3536 Register object_reg = ToRegister(instr->object()); | 3548 Register object_reg = ToRegister(instr->object()); |
| 3537 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3549 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
| 3538 // Write barrier. | 3550 // Write barrier. |
| 3539 ASSERT_NE(instr->temp_reg(), NULL); | 3551 ASSERT_NE(instr->temp_reg(), NULL); |
| 3540 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3552 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 3541 ToRegister(instr->temp_reg()), kDontSaveFPRegs); | 3553 ToRegister(instr->temp_reg()), kDontSaveFPRegs); |
| 3542 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 3554 } else if (IsFastSmiElementsKind(from_kind) && |
| 3543 to_kind == FAST_DOUBLE_ELEMENTS) { | 3555 IsFastDoubleElementsKind(to_kind)) { |
| 3544 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3556 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
| 3545 ASSERT(fixed_object_reg.is(edx)); | 3557 ASSERT(fixed_object_reg.is(edx)); |
| 3546 ASSERT(new_map_reg.is(ebx)); | 3558 ASSERT(new_map_reg.is(ebx)); |
| 3547 __ mov(fixed_object_reg, object_reg); | 3559 __ mov(fixed_object_reg, object_reg); |
| 3548 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3560 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
| 3549 RelocInfo::CODE_TARGET, instr); | 3561 RelocInfo::CODE_TARGET, instr); |
| 3550 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3562 } else if (IsFastDoubleElementsKind(from_kind) && |
| 3563 IsFastElementsKind(to_kind)) { |
| 3551 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3564 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
| 3552 ASSERT(fixed_object_reg.is(edx)); | 3565 ASSERT(fixed_object_reg.is(edx)); |
| 3553 ASSERT(new_map_reg.is(ebx)); | 3566 ASSERT(new_map_reg.is(ebx)); |
| 3554 __ mov(fixed_object_reg, object_reg); | 3567 __ mov(fixed_object_reg, object_reg); |
| 3555 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3568 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
| 3556 RelocInfo::CODE_TARGET, instr); | 3569 RelocInfo::CODE_TARGET, instr); |
| 3557 } else { | 3570 } else { |
| 3558 UNREACHABLE(); | 3571 UNREACHABLE(); |
| 3559 } | 3572 } |
| 3560 __ bind(¬_applicable); | 3573 __ bind(¬_applicable); |
| (...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4400 | 4413 |
| 4401 | 4414 |
| 4402 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4415 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| 4403 ASSERT(ToRegister(instr->context()).is(esi)); | 4416 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4404 Heap* heap = isolate()->heap(); | 4417 Heap* heap = isolate()->heap(); |
| 4405 ElementsKind boilerplate_elements_kind = | 4418 ElementsKind boilerplate_elements_kind = |
| 4406 instr->hydrogen()->boilerplate_elements_kind(); | 4419 instr->hydrogen()->boilerplate_elements_kind(); |
| 4407 | 4420 |
| 4408 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4421 // Deopt if the array literal boilerplate ElementsKind is of a type different |
| 4409 // than the expected one. The check isn't necessary if the boilerplate has | 4422 // than the expected one. The check isn't necessary if the boilerplate has |
| 4410 // already been converted to FAST_ELEMENTS. | 4423 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. |
| 4411 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4424 if (CanTransitionToMoreGeneralFastElementsKind( |
| 4425 boilerplate_elements_kind, true)) { |
| 4412 __ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object()); | 4426 __ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object()); |
| 4413 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 4427 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 4414 // Load the map's "bit field 2". We only need the first byte, | 4428 // Load the map's "bit field 2". We only need the first byte, |
| 4415 // but the following masking takes care of that anyway. | 4429 // but the following masking takes care of that anyway. |
| 4416 __ mov(ebx, FieldOperand(ebx, Map::kBitField2Offset)); | 4430 __ mov(ebx, FieldOperand(ebx, Map::kBitField2Offset)); |
| 4417 // Retrieve elements_kind from bit field 2. | 4431 // Retrieve elements_kind from bit field 2. |
| 4418 __ and_(ebx, Map::kElementsKindMask); | 4432 __ and_(ebx, Map::kElementsKindMask); |
| 4419 __ cmp(ebx, boilerplate_elements_kind << Map::kElementsKindShift); | 4433 __ cmp(ebx, boilerplate_elements_kind << Map::kElementsKindShift); |
| 4420 DeoptimizeIf(not_equal, instr->environment()); | 4434 DeoptimizeIf(not_equal, instr->environment()); |
| 4421 } | 4435 } |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5025 FixedArray::kHeaderSize - kPointerSize)); | 5039 FixedArray::kHeaderSize - kPointerSize)); |
| 5026 __ bind(&done); | 5040 __ bind(&done); |
| 5027 } | 5041 } |
| 5028 | 5042 |
| 5029 | 5043 |
| 5030 #undef __ | 5044 #undef __ |
| 5031 | 5045 |
| 5032 } } // namespace v8::internal | 5046 } } // namespace v8::internal |
| 5033 | 5047 |
| 5034 #endif // V8_TARGET_ARCH_IA32 | 5048 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |