| OLD | NEW | 
|     1 // Copyright 2011 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 | 
|    11 //       with the distribution. |    11 //       with the distribution. | 
| (...skipping 1736 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1748   int true_block = chunk_->LookupDestination(instr->true_block_id()); |  1748   int true_block = chunk_->LookupDestination(instr->true_block_id()); | 
|  1749   int false_block = chunk_->LookupDestination(instr->false_block_id()); |  1749   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 
|  1750  |  1750  | 
|  1751   __ testl(FieldOperand(input, String::kHashFieldOffset), |  1751   __ testl(FieldOperand(input, String::kHashFieldOffset), | 
|  1752            Immediate(String::kContainsCachedArrayIndexMask)); |  1752            Immediate(String::kContainsCachedArrayIndexMask)); | 
|  1753   EmitBranch(true_block, false_block, equal); |  1753   EmitBranch(true_block, false_block, equal); | 
|  1754 } |  1754 } | 
|  1755  |  1755  | 
|  1756  |  1756  | 
|  1757 // Branches to a label or falls through with the answer in the z flag. |  1757 // Branches to a label or falls through with the answer in the z flag. | 
|  1758 // Trashes the temp register and possibly input (if it and temp are aliased). |  1758 // Trashes the temp register. | 
|  1759 void LCodeGen::EmitClassOfTest(Label* is_true, |  1759 void LCodeGen::EmitClassOfTest(Label* is_true, | 
|  1760                                Label* is_false, |  1760                                Label* is_false, | 
|  1761                                Handle<String> class_name, |  1761                                Handle<String> class_name, | 
|  1762                                Register input, |  1762                                Register input, | 
|  1763                                Register temp, |  1763                                Register temp, | 
|  1764                                Register scratch) { |  1764                                Register temp2) { | 
 |  1765   ASSERT(!input.is(temp)); | 
 |  1766   ASSERT(!input.is(temp2)); | 
 |  1767   ASSERT(!temp.is(temp2)); | 
 |  1768  | 
|  1765   __ JumpIfSmi(input, is_false); |  1769   __ JumpIfSmi(input, is_false); | 
|  1766  |  1770  | 
|  1767   if (class_name->IsEqualTo(CStrVector("Function"))) { |  1771   if (class_name->IsEqualTo(CStrVector("Function"))) { | 
|  1768     // Assuming the following assertions, we can use the same compares to test |  1772     // Assuming the following assertions, we can use the same compares to test | 
|  1769     // for both being a function type and being in the object type range. |  1773     // for both being a function type and being in the object type range. | 
|  1770     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |  1774     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 
|  1771     STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == |  1775     STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == | 
|  1772                   FIRST_SPEC_OBJECT_TYPE + 1); |  1776                   FIRST_SPEC_OBJECT_TYPE + 1); | 
|  1773     STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == |  1777     STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == | 
|  1774                   LAST_SPEC_OBJECT_TYPE - 1); |  1778                   LAST_SPEC_OBJECT_TYPE - 1); | 
|  1775     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |  1779     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 
|  1776     __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); |  1780     __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); | 
|  1777     __ j(below, is_false); |  1781     __ j(below, is_false); | 
|  1778     __ j(equal, is_true); |  1782     __ j(equal, is_true); | 
|  1779     __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); |  1783     __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); | 
|  1780     __ j(equal, is_true); |  1784     __ j(equal, is_true); | 
|  1781   } else { |  1785   } else { | 
|  1782     // Faster code path to avoid two compares: subtract lower bound from the |  1786     // Faster code path to avoid two compares: subtract lower bound from the | 
|  1783     // actual type and do a signed compare with the width of the type range. |  1787     // actual type and do a signed compare with the width of the type range. | 
|  1784     __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |  1788     __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 
|  1785     __ movq(scratch, FieldOperand(temp, Map::kInstanceTypeOffset)); |  1789     __ movq(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); | 
|  1786     __ subb(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |  1790     __ subb(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 
|  1787     __ cmpb(scratch, |  1791     __ cmpb(temp2, | 
|  1788             Immediate(static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - |  1792             Immediate(static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - | 
|  1789                                           FIRST_NONCALLABLE_SPEC_OBJECT_TYPE))); |  1793                                           FIRST_NONCALLABLE_SPEC_OBJECT_TYPE))); | 
|  1790     __ j(above, is_false); |  1794     __ j(above, is_false); | 
|  1791   } |  1795   } | 
|  1792  |  1796  | 
|  1793   // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. |  1797   // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. | 
|  1794   // Check if the constructor in the map is a function. |  1798   // Check if the constructor in the map is a function. | 
|  1795   __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); |  1799   __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); | 
|  1796  |  1800  | 
|  1797   // Objects with a non-function constructor have class 'Object'. |  1801   // Objects with a non-function constructor have class 'Object'. | 
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1890   __ JumpIfSmi(object, &false_result); |  1894   __ JumpIfSmi(object, &false_result); | 
|  1891  |  1895  | 
|  1892   // This is the inlined call site instanceof cache. The two occurences of the |  1896   // This is the inlined call site instanceof cache. The two occurences of the | 
|  1893   // hole value will be patched to the last map/result pair generated by the |  1897   // hole value will be patched to the last map/result pair generated by the | 
|  1894   // instanceof stub. |  1898   // instanceof stub. | 
|  1895   Label cache_miss; |  1899   Label cache_miss; | 
|  1896   // Use a temp register to avoid memory operands with variable lengths. |  1900   // Use a temp register to avoid memory operands with variable lengths. | 
|  1897   Register map = ToRegister(instr->TempAt(0)); |  1901   Register map = ToRegister(instr->TempAt(0)); | 
|  1898   __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |  1902   __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 
|  1899   __ bind(deferred->map_check());  // Label for calculating code patching. |  1903   __ bind(deferred->map_check());  // Label for calculating code patching. | 
|  1900   __ movq(kScratchRegister, factory()->the_hole_value(), |  1904   Handle<JSGlobalPropertyCell> cache_cell = | 
|  1901           RelocInfo::EMBEDDED_OBJECT); |  1905       factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); | 
|  1902   __ cmpq(map, kScratchRegister);  // Patched to cached map. |  1906   __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); | 
 |  1907   __ cmpq(map, Operand(kScratchRegister, 0)); | 
|  1903   __ j(not_equal, &cache_miss, Label::kNear); |  1908   __ j(not_equal, &cache_miss, Label::kNear); | 
|  1904   // Patched to load either true or false. |  1909   // Patched to load either true or false. | 
|  1905   __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |  1910   __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 
|  1906 #ifdef DEBUG |  1911 #ifdef DEBUG | 
|  1907   // Check that the code size between patch label and patch sites is invariant. |  1912   // Check that the code size between patch label and patch sites is invariant. | 
|  1908   Label end_of_patched_code; |  1913   Label end_of_patched_code; | 
|  1909   __ bind(&end_of_patched_code); |  1914   __ bind(&end_of_patched_code); | 
|  1910   ASSERT(true); |  1915   ASSERT(true); | 
|  1911 #endif |  1916 #endif | 
|  1912   __ jmp(&done); |  1917   __ jmp(&done); | 
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2629   RecordPosition(pointers->position()); |  2634   RecordPosition(pointers->position()); | 
|  2630  |  2635  | 
|  2631   // Invoke function. |  2636   // Invoke function. | 
|  2632   __ SetCallKind(rcx, call_kind); |  2637   __ SetCallKind(rcx, call_kind); | 
|  2633   if (*function == *info()->closure()) { |  2638   if (*function == *info()->closure()) { | 
|  2634     __ CallSelf(); |  2639     __ CallSelf(); | 
|  2635   } else { |  2640   } else { | 
|  2636     __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |  2641     __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 
|  2637   } |  2642   } | 
|  2638  |  2643  | 
|  2639   // Setup deoptimization. |  2644   // Set up deoptimization. | 
|  2640   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |  2645   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 
|  2641  |  2646  | 
|  2642   // Restore context. |  2647   // Restore context. | 
|  2643   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |  2648   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 
|  2644 } |  2649 } | 
|  2645  |  2650  | 
|  2646  |  2651  | 
|  2647 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |  2652 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 
|  2648   ASSERT(ToRegister(instr->result()).is(rax)); |  2653   ASSERT(ToRegister(instr->result()).is(rax)); | 
|  2649   __ LoadHeapObject(rdi, instr->function()); |  2654   __ LoadHeapObject(rdi, instr->function()); | 
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2919     MathPowStub stub(MathPowStub::INTEGER); |  2924     MathPowStub stub(MathPowStub::INTEGER); | 
|  2920     __ CallStub(&stub); |  2925     __ CallStub(&stub); | 
|  2921   } else { |  2926   } else { | 
|  2922     ASSERT(exponent_type.IsDouble()); |  2927     ASSERT(exponent_type.IsDouble()); | 
|  2923     MathPowStub stub(MathPowStub::DOUBLE); |  2928     MathPowStub stub(MathPowStub::DOUBLE); | 
|  2924     __ CallStub(&stub); |  2929     __ CallStub(&stub); | 
|  2925   } |  2930   } | 
|  2926 } |  2931 } | 
|  2927  |  2932  | 
|  2928  |  2933  | 
 |  2934 void LCodeGen::DoRandom(LRandom* instr) { | 
 |  2935   // Having marked this instruction as a call we can use any | 
 |  2936   // registers. | 
 |  2937   ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 
 |  2938  | 
 |  2939   // Choose the right register for the first argument depending on | 
 |  2940   // calling convention. | 
 |  2941 #ifdef _WIN64 | 
 |  2942   ASSERT(ToRegister(instr->InputAt(0)).is(rcx)); | 
 |  2943   Register global_object = rcx; | 
 |  2944 #else | 
 |  2945   ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); | 
 |  2946   Register global_object = rdi; | 
 |  2947 #endif | 
 |  2948  | 
 |  2949   __ PrepareCallCFunction(1); | 
 |  2950   __ movq(global_object, | 
 |  2951           FieldOperand(global_object, GlobalObject::kGlobalContextOffset)); | 
 |  2952   __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 
 |  2953  | 
 |  2954   // Convert 32 random bits in rax to 0.(32 random bits) in a double | 
 |  2955   // by computing: | 
 |  2956   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 
 |  2957   __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single. | 
 |  2958   __ movd(xmm2, rcx); | 
 |  2959   __ movd(xmm1, rax); | 
 |  2960   __ cvtss2sd(xmm2, xmm2); | 
 |  2961   __ xorps(xmm1, xmm2); | 
 |  2962   __ subsd(xmm1, xmm2); | 
 |  2963 } | 
 |  2964  | 
 |  2965  | 
|  2929 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |  2966 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 
|  2930   ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |  2967   ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 
|  2931   TranscendentalCacheStub stub(TranscendentalCache::LOG, |  2968   TranscendentalCacheStub stub(TranscendentalCache::LOG, | 
|  2932                                TranscendentalCacheStub::UNTAGGED); |  2969                                TranscendentalCacheStub::UNTAGGED); | 
|  2933   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |  2970   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 
|  2934 } |  2971 } | 
|  2935  |  2972  | 
|  2936  |  2973  | 
|  2937 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) { |  2974 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) { | 
|  2938   ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |  2975   ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3503     Condition is_smi = __ CheckSmi(input); |  3540     Condition is_smi = __ CheckSmi(input); | 
|  3504     DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |  3541     DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 
|  3505   } |  3542   } | 
|  3506   __ SmiToInteger32(input, input); |  3543   __ SmiToInteger32(input, input); | 
|  3507 } |  3544 } | 
|  3508  |  3545  | 
|  3509  |  3546  | 
|  3510 void LCodeGen::EmitNumberUntagD(Register input_reg, |  3547 void LCodeGen::EmitNumberUntagD(Register input_reg, | 
|  3511                                 XMMRegister result_reg, |  3548                                 XMMRegister result_reg, | 
|  3512                                 bool deoptimize_on_undefined, |  3549                                 bool deoptimize_on_undefined, | 
 |  3550                                 bool deoptimize_on_minus_zero, | 
|  3513                                 LEnvironment* env) { |  3551                                 LEnvironment* env) { | 
|  3514   Label load_smi, done; |  3552   Label load_smi, done; | 
|  3515  |  3553  | 
|  3516   // Smi check. |  3554   // Smi check. | 
|  3517   __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |  3555   __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 
|  3518  |  3556  | 
|  3519   // Heap number map check. |  3557   // Heap number map check. | 
|  3520   __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |  3558   __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 
|  3521                  Heap::kHeapNumberMapRootIndex); |  3559                  Heap::kHeapNumberMapRootIndex); | 
|  3522   if (deoptimize_on_undefined) { |  3560   if (deoptimize_on_undefined) { | 
|  3523     DeoptimizeIf(not_equal, env); |  3561     DeoptimizeIf(not_equal, env); | 
|  3524   } else { |  3562   } else { | 
|  3525     Label heap_number; |  3563     Label heap_number; | 
|  3526     __ j(equal, &heap_number, Label::kNear); |  3564     __ j(equal, &heap_number, Label::kNear); | 
|  3527  |  3565  | 
|  3528     __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |  3566     __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 
|  3529     DeoptimizeIf(not_equal, env); |  3567     DeoptimizeIf(not_equal, env); | 
|  3530  |  3568  | 
|  3531     // Convert undefined to NaN. Compute NaN as 0/0. |  3569     // Convert undefined to NaN. Compute NaN as 0/0. | 
|  3532     __ xorps(result_reg, result_reg); |  3570     __ xorps(result_reg, result_reg); | 
|  3533     __ divsd(result_reg, result_reg); |  3571     __ divsd(result_reg, result_reg); | 
|  3534     __ jmp(&done, Label::kNear); |  3572     __ jmp(&done, Label::kNear); | 
|  3535  |  3573  | 
|  3536     __ bind(&heap_number); |  3574     __ bind(&heap_number); | 
|  3537   } |  3575   } | 
|  3538   // Heap number to XMM conversion. |  3576   // Heap number to XMM conversion. | 
|  3539   __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |  3577   __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 
 |  3578   if (deoptimize_on_minus_zero) { | 
 |  3579     XMMRegister xmm_scratch = xmm0; | 
 |  3580     __ xorps(xmm_scratch, xmm_scratch); | 
 |  3581     __ ucomisd(xmm_scratch, result_reg); | 
 |  3582     __ j(not_equal, &done, Label::kNear); | 
 |  3583     __ movmskpd(kScratchRegister, result_reg); | 
 |  3584     __ testq(kScratchRegister, Immediate(1)); | 
 |  3585     DeoptimizeIf(not_zero, env); | 
 |  3586   } | 
|  3540   __ jmp(&done, Label::kNear); |  3587   __ jmp(&done, Label::kNear); | 
|  3541  |  3588  | 
|  3542   // Smi to XMM conversion |  3589   // Smi to XMM conversion | 
|  3543   __ bind(&load_smi); |  3590   __ bind(&load_smi); | 
|  3544   __ SmiToInteger32(kScratchRegister, input_reg); |  3591   __ SmiToInteger32(kScratchRegister, input_reg); | 
|  3545   __ cvtlsi2sd(result_reg, kScratchRegister); |  3592   __ cvtlsi2sd(result_reg, kScratchRegister); | 
|  3546   __ bind(&done); |  3593   __ bind(&done); | 
|  3547 } |  3594 } | 
|  3548  |  3595  | 
|  3549  |  3596  | 
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3621   LOperand* input = instr->InputAt(0); |  3668   LOperand* input = instr->InputAt(0); | 
|  3622   ASSERT(input->IsRegister()); |  3669   ASSERT(input->IsRegister()); | 
|  3623   LOperand* result = instr->result(); |  3670   LOperand* result = instr->result(); | 
|  3624   ASSERT(result->IsDoubleRegister()); |  3671   ASSERT(result->IsDoubleRegister()); | 
|  3625  |  3672  | 
|  3626   Register input_reg = ToRegister(input); |  3673   Register input_reg = ToRegister(input); | 
|  3627   XMMRegister result_reg = ToDoubleRegister(result); |  3674   XMMRegister result_reg = ToDoubleRegister(result); | 
|  3628  |  3675  | 
|  3629   EmitNumberUntagD(input_reg, result_reg, |  3676   EmitNumberUntagD(input_reg, result_reg, | 
|  3630                    instr->hydrogen()->deoptimize_on_undefined(), |  3677                    instr->hydrogen()->deoptimize_on_undefined(), | 
 |  3678                    instr->hydrogen()->deoptimize_on_minus_zero(), | 
|  3631                    instr->environment()); |  3679                    instr->environment()); | 
|  3632 } |  3680 } | 
|  3633  |  3681  | 
|  3634  |  3682  | 
|  3635 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |  3683 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 
|  3636   LOperand* input = instr->InputAt(0); |  3684   LOperand* input = instr->InputAt(0); | 
|  3637   ASSERT(input->IsDoubleRegister()); |  3685   ASSERT(input->IsDoubleRegister()); | 
|  3638   LOperand* result = instr->result(); |  3686   LOperand* result = instr->result(); | 
|  3639   ASSERT(result->IsRegister()); |  3687   ASSERT(result->IsRegister()); | 
|  3640  |  3688  | 
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3740         isolate()->factory()->NewJSGlobalPropertyCell(target); |  3788         isolate()->factory()->NewJSGlobalPropertyCell(target); | 
|  3741     __ movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL); |  3789     __ movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL); | 
|  3742     __ cmpq(reg, Operand(kScratchRegister, 0)); |  3790     __ cmpq(reg, Operand(kScratchRegister, 0)); | 
|  3743   } else { |  3791   } else { | 
|  3744     __ Cmp(reg, target); |  3792     __ Cmp(reg, target); | 
|  3745   } |  3793   } | 
|  3746   DeoptimizeIf(not_equal, instr->environment()); |  3794   DeoptimizeIf(not_equal, instr->environment()); | 
|  3747 } |  3795 } | 
|  3748  |  3796  | 
|  3749  |  3797  | 
 |  3798 void LCodeGen::DoCheckMapCommon(Register reg, | 
 |  3799                                 Handle<Map> map, | 
 |  3800                                 CompareMapMode mode, | 
 |  3801                                 LEnvironment* env) { | 
 |  3802   Label success; | 
 |  3803   __ CompareMap(reg, map, &success, mode); | 
 |  3804   DeoptimizeIf(not_equal, env); | 
 |  3805   __ bind(&success); | 
 |  3806 } | 
 |  3807  | 
 |  3808  | 
|  3750 void LCodeGen::DoCheckMap(LCheckMap* instr) { |  3809 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 
|  3751   LOperand* input = instr->InputAt(0); |  3810   LOperand* input = instr->InputAt(0); | 
|  3752   ASSERT(input->IsRegister()); |  3811   ASSERT(input->IsRegister()); | 
|  3753   Register reg = ToRegister(input); |  3812   Register reg = ToRegister(input); | 
|  3754   __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), |  3813   Handle<Map> map = instr->hydrogen()->map(); | 
|  3755          instr->hydrogen()->map()); |  3814   DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment()); | 
|  3756   DeoptimizeIf(not_equal, instr->environment()); |  | 
|  3757 } |  3815 } | 
|  3758  |  3816  | 
|  3759  |  3817  | 
|  3760 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |  3818 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 
|  3761   XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |  3819   XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 
|  3762   Register result_reg = ToRegister(instr->result()); |  3820   Register result_reg = ToRegister(instr->result()); | 
|  3763   Register temp_reg = ToRegister(instr->TempAt(0)); |  3821   Register temp_reg = ToRegister(instr->TempAt(0)); | 
|  3764   __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); |  3822   __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); | 
|  3765 } |  3823 } | 
|  3766  |  3824  | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3812   Register reg = ToRegister(instr->TempAt(0)); |  3870   Register reg = ToRegister(instr->TempAt(0)); | 
|  3813  |  3871  | 
|  3814   Handle<JSObject> holder = instr->holder(); |  3872   Handle<JSObject> holder = instr->holder(); | 
|  3815   Handle<JSObject> current_prototype = instr->prototype(); |  3873   Handle<JSObject> current_prototype = instr->prototype(); | 
|  3816  |  3874  | 
|  3817   // Load prototype object. |  3875   // Load prototype object. | 
|  3818   __ LoadHeapObject(reg, current_prototype); |  3876   __ LoadHeapObject(reg, current_prototype); | 
|  3819  |  3877  | 
|  3820   // Check prototype maps up to the holder. |  3878   // Check prototype maps up to the holder. | 
|  3821   while (!current_prototype.is_identical_to(holder)) { |  3879   while (!current_prototype.is_identical_to(holder)) { | 
|  3822     __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), |  3880     DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), | 
|  3823            Handle<Map>(current_prototype->map())); |  3881                      ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); | 
|  3824     DeoptimizeIf(not_equal, instr->environment()); |  | 
|  3825     current_prototype = |  3882     current_prototype = | 
|  3826         Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |  3883         Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); | 
|  3827     // Load next prototype object. |  3884     // Load next prototype object. | 
|  3828     __ LoadHeapObject(reg, current_prototype); |  3885     __ LoadHeapObject(reg, current_prototype); | 
|  3829   } |  3886   } | 
|  3830  |  3887  | 
|  3831   // Check the holder map. |  3888   // Check the holder map. | 
|  3832   __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), |  3889     DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), | 
|  3833          Handle<Map>(current_prototype->map())); |  3890                      ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); | 
|  3834   DeoptimizeIf(not_equal, instr->environment()); |  | 
|  3835 } |  3891 } | 
|  3836  |  3892  | 
|  3837  |  3893  | 
|  3838 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |  3894 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 
|  3839   Heap* heap = isolate()->heap(); |  3895   Heap* heap = isolate()->heap(); | 
|  3840   ElementsKind boilerplate_elements_kind = |  3896   ElementsKind boilerplate_elements_kind = | 
|  3841       instr->hydrogen()->boilerplate_elements_kind(); |  3897       instr->hydrogen()->boilerplate_elements_kind(); | 
|  3842  |  3898  | 
|  3843   // Deopt if the array literal boilerplate ElementsKind is of a type different |  3899   // Deopt if the array literal boilerplate ElementsKind is of a type different | 
|  3844   // than the expected one. The check isn't necessary if the boilerplate has |  3900   // than the expected one. The check isn't necessary if the boilerplate has | 
|  3845   // already been converted to FAST_ELEMENTS. |  3901   // already been converted to FAST_ELEMENTS. | 
|  3846   if (boilerplate_elements_kind != FAST_ELEMENTS) { |  3902   if (boilerplate_elements_kind != FAST_ELEMENTS) { | 
|  3847     __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); |  3903     __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); | 
|  3848     __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |  3904     __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 
|  3849     // Load the map's "bit field 2". |  3905     // Load the map's "bit field 2". | 
|  3850     __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); |  3906     __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); | 
|  3851     // Retrieve elements_kind from bit field 2. |  3907     // Retrieve elements_kind from bit field 2. | 
|  3852     __ and_(rbx, Immediate(Map::kElementsKindMask)); |  3908     __ and_(rbx, Immediate(Map::kElementsKindMask)); | 
|  3853     __ cmpb(rbx, Immediate(boilerplate_elements_kind << |  3909     __ cmpb(rbx, Immediate(boilerplate_elements_kind << | 
|  3854                            Map::kElementsKindShift)); |  3910                            Map::kElementsKindShift)); | 
|  3855     DeoptimizeIf(not_equal, instr->environment()); |  3911     DeoptimizeIf(not_equal, instr->environment()); | 
|  3856   } |  3912   } | 
|  3857  |  3913  | 
|  3858   // Setup the parameters to the stub/runtime call. |  3914   // Set up the parameters to the stub/runtime call. | 
|  3859   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |  3915   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 
|  3860   __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); |  3916   __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); | 
|  3861   __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |  3917   __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 
|  3862   // Boilerplate already exists, constant elements are never accessed. |  3918   // Boilerplate already exists, constant elements are never accessed. | 
|  3863   // Pass an empty fixed array. |  3919   // Pass an empty fixed array. | 
|  3864   __ Push(Handle<FixedArray>(heap->empty_fixed_array())); |  3920   __ Push(Handle<FixedArray>(heap->empty_fixed_array())); | 
|  3865  |  3921  | 
|  3866   // Pick the right runtime function or stub to call. |  3922   // Pick the right runtime function or stub to call. | 
|  3867   int length = instr->hydrogen()->length(); |  3923   int length = instr->hydrogen()->length(); | 
|  3868   if (instr->hydrogen()->IsCopyOnWrite()) { |  3924   if (instr->hydrogen()->IsCopyOnWrite()) { | 
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3949   __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); |  4005   __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); | 
|  3950   EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset); |  4006   EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset); | 
|  3951   ASSERT_EQ(size, offset); |  4007   ASSERT_EQ(size, offset); | 
|  3952 } |  4008 } | 
|  3953  |  4009  | 
|  3954  |  4010  | 
|  3955 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { |  4011 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { | 
|  3956   Handle<FixedArray> constant_properties = |  4012   Handle<FixedArray> constant_properties = | 
|  3957       instr->hydrogen()->constant_properties(); |  4013       instr->hydrogen()->constant_properties(); | 
|  3958  |  4014  | 
|  3959   // Setup the parameters to the stub/runtime call. |  4015   // Set up the parameters to the stub/runtime call. | 
|  3960   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |  4016   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 
|  3961   __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); |  4017   __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); | 
|  3962   __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |  4018   __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 
|  3963   __ Push(constant_properties); |  4019   __ Push(constant_properties); | 
|  3964   int flags = instr->hydrogen()->fast_elements() |  4020   int flags = instr->hydrogen()->fast_elements() | 
|  3965       ? ObjectLiteral::kFastElements |  4021       ? ObjectLiteral::kFastElements | 
|  3966       : ObjectLiteral::kNoFlags; |  4022       : ObjectLiteral::kNoFlags; | 
|  3967   flags |= instr->hydrogen()->has_function() |  4023   flags |= instr->hydrogen()->has_function() | 
|  3968       ? ObjectLiteral::kHasFunction |  4024       ? ObjectLiteral::kHasFunction | 
|  3969       : ObjectLiteral::kNoFlags; |  4025       : ObjectLiteral::kNoFlags; | 
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  4329   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |  4385   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 
|  4330   ASSERT(osr_pc_offset_ == -1); |  4386   ASSERT(osr_pc_offset_ == -1); | 
|  4331   osr_pc_offset_ = masm()->pc_offset(); |  4387   osr_pc_offset_ = masm()->pc_offset(); | 
|  4332 } |  4388 } | 
|  4333  |  4389  | 
|  4334 #undef __ |  4390 #undef __ | 
|  4335  |  4391  | 
|  4336 } }  // namespace v8::internal |  4392 } }  // namespace v8::internal | 
|  4337  |  4393  | 
|  4338 #endif  // V8_TARGET_ARCH_X64 |  4394 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW |