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 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 } | 252 } |
253 } | 253 } |
254 | 254 |
255 | 255 |
256 bool LCodeGen::GenerateDeferredCode() { | 256 bool LCodeGen::GenerateDeferredCode() { |
257 ASSERT(is_generating()); | 257 ASSERT(is_generating()); |
258 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 258 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
259 LDeferredCode* code = deferred_[i]; | 259 LDeferredCode* code = deferred_[i]; |
260 __ bind(code->entry()); | 260 __ bind(code->entry()); |
261 code->Generate(); | 261 code->Generate(); |
262 __ jmp(code->exit()); | |
263 } | 262 } |
264 | 263 |
265 // Deferred code is the last part of the instruction sequence. Mark | 264 // Deferred code is the last part of the instruction sequence. Mark |
266 // the generated code as done unless we bailed out. | 265 // the generated code as done unless we bailed out. |
267 if (!is_aborted()) status_ = DONE; | 266 if (!is_aborted()) status_ = DONE; |
268 return !is_aborted(); | 267 return !is_aborted(); |
269 } | 268 } |
270 | 269 |
271 | 270 |
272 bool LCodeGen::GenerateSafepointTable() { | 271 bool LCodeGen::GenerateSafepointTable() { |
(...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 break; | 1457 break; |
1459 case Token::IN: | 1458 case Token::IN: |
1460 case Token::INSTANCEOF: | 1459 case Token::INSTANCEOF: |
1461 default: | 1460 default: |
1462 UNREACHABLE(); | 1461 UNREACHABLE(); |
1463 } | 1462 } |
1464 return cond; | 1463 return cond; |
1465 } | 1464 } |
1466 | 1465 |
1467 | 1466 |
| 1467 void LCodeGen::EmitPush(LOperand* operand) { |
| 1468 if (operand->IsRegister()) { |
| 1469 __ push(ToRegister(operand)); |
| 1470 } else if (operand->IsConstantOperand()) { |
| 1471 __ push(ToImmediate(operand)); |
| 1472 } else { |
| 1473 __ push(ToOperand(operand)); |
| 1474 } |
| 1475 } |
| 1476 |
| 1477 |
1468 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { | 1478 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { |
1469 if (right->IsConstantOperand()) { | 1479 if (right->IsConstantOperand()) { |
1470 __ cmp(ToOperand(left), ToImmediate(right)); | 1480 __ cmp(ToOperand(left), ToImmediate(right)); |
1471 } else { | 1481 } else { |
1472 __ cmp(ToRegister(left), ToOperand(right)); | 1482 __ cmp(ToRegister(left), ToOperand(right)); |
1473 } | 1483 } |
1474 } | 1484 } |
1475 | 1485 |
1476 | 1486 |
1477 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1487 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1781 | 1791 |
1782 | 1792 |
1783 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 1793 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
1784 class DeferredInstanceOfKnownGlobal: public LDeferredCode { | 1794 class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
1785 public: | 1795 public: |
1786 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 1796 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
1787 LInstanceOfKnownGlobal* instr) | 1797 LInstanceOfKnownGlobal* instr) |
1788 : LDeferredCode(codegen), instr_(instr) { } | 1798 : LDeferredCode(codegen), instr_(instr) { } |
1789 virtual void Generate() { | 1799 virtual void Generate() { |
1790 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); | 1800 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); |
| 1801 __ jmp(exit()); |
1791 } | 1802 } |
1792 | 1803 |
1793 Label* map_check() { return &map_check_; } | 1804 Label* map_check() { return &map_check_; } |
1794 | 1805 |
1795 private: | 1806 private: |
1796 LInstanceOfKnownGlobal* instr_; | 1807 LInstanceOfKnownGlobal* instr_; |
1797 Label map_check_; | 1808 Label map_check_; |
1798 }; | 1809 }; |
1799 | 1810 |
1800 DeferredInstanceOfKnownGlobal* deferred; | 1811 DeferredInstanceOfKnownGlobal* deferred; |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2427 pointers, | 2438 pointers, |
2428 env->deoptimization_index()); | 2439 env->deoptimization_index()); |
2429 ParameterCount actual(eax); | 2440 ParameterCount actual(eax); |
2430 __ InvokeFunction(function, actual, CALL_FUNCTION, | 2441 __ InvokeFunction(function, actual, CALL_FUNCTION, |
2431 safepoint_generator, CALL_AS_METHOD); | 2442 safepoint_generator, CALL_AS_METHOD); |
2432 } | 2443 } |
2433 | 2444 |
2434 | 2445 |
2435 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2446 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
2436 LOperand* argument = instr->InputAt(0); | 2447 LOperand* argument = instr->InputAt(0); |
2437 if (argument->IsConstantOperand()) { | 2448 EmitPush(argument); |
2438 __ push(ToImmediate(argument)); | |
2439 } else { | |
2440 __ push(ToOperand(argument)); | |
2441 } | |
2442 } | 2449 } |
2443 | 2450 |
2444 | 2451 |
2445 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 2452 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
2446 Register result = ToRegister(instr->result()); | 2453 Register result = ToRegister(instr->result()); |
2447 __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 2454 __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
2448 } | 2455 } |
2449 | 2456 |
2450 | 2457 |
2451 void LCodeGen::DoContext(LContext* instr) { | 2458 void LCodeGen::DoContext(LContext* instr) { |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 | 2596 |
2590 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2597 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
2591 // Class for deferred case. | 2598 // Class for deferred case. |
2592 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2599 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
2593 public: | 2600 public: |
2594 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2601 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
2595 LUnaryMathOperation* instr) | 2602 LUnaryMathOperation* instr) |
2596 : LDeferredCode(codegen), instr_(instr) { } | 2603 : LDeferredCode(codegen), instr_(instr) { } |
2597 virtual void Generate() { | 2604 virtual void Generate() { |
2598 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2605 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 2606 __ jmp(exit()); |
2599 } | 2607 } |
2600 private: | 2608 private: |
2601 LUnaryMathOperation* instr_; | 2609 LUnaryMathOperation* instr_; |
2602 }; | 2610 }; |
2603 | 2611 |
2604 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2612 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
2605 Representation r = instr->hydrogen()->value()->representation(); | 2613 Representation r = instr->hydrogen()->value()->representation(); |
2606 | 2614 |
2607 if (r.IsDouble()) { | 2615 if (r.IsDouble()) { |
2608 XMMRegister scratch = xmm0; | 2616 XMMRegister scratch = xmm0; |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3066 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3074 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3067 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 3075 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); |
3068 } | 3076 } |
3069 | 3077 |
3070 | 3078 |
3071 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 3079 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
3072 class DeferredStringCharCodeAt: public LDeferredCode { | 3080 class DeferredStringCharCodeAt: public LDeferredCode { |
3073 public: | 3081 public: |
3074 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 3082 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
3075 : LDeferredCode(codegen), instr_(instr) { } | 3083 : LDeferredCode(codegen), instr_(instr) { } |
3076 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 3084 virtual void Generate() { |
| 3085 codegen()->DoDeferredStringCharCodeAt(instr_); |
| 3086 __ jmp(exit()); |
| 3087 } |
3077 private: | 3088 private: |
3078 LStringCharCodeAt* instr_; | 3089 LStringCharCodeAt* instr_; |
3079 }; | 3090 }; |
3080 | 3091 |
3081 Register string = ToRegister(instr->string()); | 3092 Register string = ToRegister(instr->string()); |
3082 Register index = no_reg; | 3093 Register index = no_reg; |
3083 int const_index = -1; | 3094 int const_index = -1; |
3084 if (instr->index()->IsConstantOperand()) { | 3095 if (instr->index()->IsConstantOperand()) { |
3085 const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3096 const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
3086 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 3097 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3202 __ SmiUntag(eax); | 3213 __ SmiUntag(eax); |
3203 __ StoreToSafepointRegisterSlot(result, eax); | 3214 __ StoreToSafepointRegisterSlot(result, eax); |
3204 } | 3215 } |
3205 | 3216 |
3206 | 3217 |
3207 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 3218 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
3208 class DeferredStringCharFromCode: public LDeferredCode { | 3219 class DeferredStringCharFromCode: public LDeferredCode { |
3209 public: | 3220 public: |
3210 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 3221 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
3211 : LDeferredCode(codegen), instr_(instr) { } | 3222 : LDeferredCode(codegen), instr_(instr) { } |
3212 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 3223 virtual void Generate() { |
| 3224 codegen()->DoDeferredStringCharFromCode(instr_); |
| 3225 __ jmp(exit()); |
| 3226 } |
3213 private: | 3227 private: |
3214 LStringCharFromCode* instr_; | 3228 LStringCharFromCode* instr_; |
3215 }; | 3229 }; |
3216 | 3230 |
3217 DeferredStringCharFromCode* deferred = | 3231 DeferredStringCharFromCode* deferred = |
3218 new DeferredStringCharFromCode(this, instr); | 3232 new DeferredStringCharFromCode(this, instr); |
3219 | 3233 |
3220 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 3234 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
3221 Register char_code = ToRegister(instr->char_code()); | 3235 Register char_code = ToRegister(instr->char_code()); |
3222 Register result = ToRegister(instr->result()); | 3236 Register result = ToRegister(instr->result()); |
(...skipping 29 matching lines...) Expand all Loading... |
3252 | 3266 |
3253 | 3267 |
3254 void LCodeGen::DoStringLength(LStringLength* instr) { | 3268 void LCodeGen::DoStringLength(LStringLength* instr) { |
3255 Register string = ToRegister(instr->string()); | 3269 Register string = ToRegister(instr->string()); |
3256 Register result = ToRegister(instr->result()); | 3270 Register result = ToRegister(instr->result()); |
3257 __ mov(result, FieldOperand(string, String::kLengthOffset)); | 3271 __ mov(result, FieldOperand(string, String::kLengthOffset)); |
3258 } | 3272 } |
3259 | 3273 |
3260 | 3274 |
3261 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 3275 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
3262 if (instr->left()->IsConstantOperand()) { | 3276 EmitPush(instr->left()); |
3263 __ push(ToImmediate(instr->left())); | 3277 EmitPush(instr->right()); |
3264 } else { | |
3265 __ push(ToOperand(instr->left())); | |
3266 } | |
3267 if (instr->right()->IsConstantOperand()) { | |
3268 __ push(ToImmediate(instr->right())); | |
3269 } else { | |
3270 __ push(ToOperand(instr->right())); | |
3271 } | |
3272 StringAddStub stub(NO_STRING_CHECK_IN_STUB); | 3278 StringAddStub stub(NO_STRING_CHECK_IN_STUB); |
3273 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3279 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
3274 } | 3280 } |
3275 | 3281 |
3276 | 3282 |
3277 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 3283 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
3278 LOperand* input = instr->InputAt(0); | 3284 LOperand* input = instr->InputAt(0); |
3279 ASSERT(input->IsRegister() || input->IsStackSlot()); | 3285 ASSERT(input->IsRegister() || input->IsStackSlot()); |
3280 LOperand* output = instr->result(); | 3286 LOperand* output = instr->result(); |
3281 ASSERT(output->IsDoubleRegister()); | 3287 ASSERT(output->IsDoubleRegister()); |
3282 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 3288 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
3283 } | 3289 } |
3284 | 3290 |
3285 | 3291 |
3286 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 3292 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
3287 class DeferredNumberTagI: public LDeferredCode { | 3293 class DeferredNumberTagI: public LDeferredCode { |
3288 public: | 3294 public: |
3289 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 3295 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
3290 : LDeferredCode(codegen), instr_(instr) { } | 3296 : LDeferredCode(codegen), instr_(instr) { } |
3291 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } | 3297 virtual void Generate() { |
| 3298 codegen()->DoDeferredNumberTagI(instr_); |
| 3299 __ jmp(exit()); |
| 3300 } |
3292 private: | 3301 private: |
3293 LNumberTagI* instr_; | 3302 LNumberTagI* instr_; |
3294 }; | 3303 }; |
3295 | 3304 |
3296 LOperand* input = instr->InputAt(0); | 3305 LOperand* input = instr->InputAt(0); |
3297 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3306 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
3298 Register reg = ToRegister(input); | 3307 Register reg = ToRegister(input); |
3299 | 3308 |
3300 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 3309 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
3301 __ SmiTag(reg); | 3310 __ SmiTag(reg); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3341 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); | 3350 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); |
3342 __ StoreToSafepointRegisterSlot(reg, reg); | 3351 __ StoreToSafepointRegisterSlot(reg, reg); |
3343 } | 3352 } |
3344 | 3353 |
3345 | 3354 |
3346 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 3355 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
3347 class DeferredNumberTagD: public LDeferredCode { | 3356 class DeferredNumberTagD: public LDeferredCode { |
3348 public: | 3357 public: |
3349 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 3358 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
3350 : LDeferredCode(codegen), instr_(instr) { } | 3359 : LDeferredCode(codegen), instr_(instr) { } |
3351 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 3360 virtual void Generate() { |
| 3361 codegen()->DoDeferredNumberTagD(instr_); |
| 3362 __ jmp(exit()); |
| 3363 } |
3352 private: | 3364 private: |
3353 LNumberTagD* instr_; | 3365 LNumberTagD* instr_; |
3354 }; | 3366 }; |
3355 | 3367 |
3356 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 3368 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
3357 Register reg = ToRegister(instr->result()); | 3369 Register reg = ToRegister(instr->result()); |
3358 Register tmp = ToRegister(instr->TempAt(0)); | 3370 Register tmp = ToRegister(instr->TempAt(0)); |
3359 | 3371 |
3360 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | 3372 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
3361 if (FLAG_inline_new) { | 3373 if (FLAG_inline_new) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3438 __ cvtsi2sd(result_reg, Operand(input_reg)); | 3450 __ cvtsi2sd(result_reg, Operand(input_reg)); |
3439 __ SmiTag(input_reg); // Retag smi. | 3451 __ SmiTag(input_reg); // Retag smi. |
3440 __ bind(&done); | 3452 __ bind(&done); |
3441 } | 3453 } |
3442 | 3454 |
3443 | 3455 |
3444 class DeferredTaggedToI: public LDeferredCode { | 3456 class DeferredTaggedToI: public LDeferredCode { |
3445 public: | 3457 public: |
3446 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3458 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
3447 : LDeferredCode(codegen), instr_(instr) { } | 3459 : LDeferredCode(codegen), instr_(instr) { } |
3448 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3460 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_, exit()); } |
3449 private: | 3461 private: |
3450 LTaggedToI* instr_; | 3462 LTaggedToI* instr_; |
3451 }; | 3463 }; |
3452 | 3464 |
3453 | 3465 |
3454 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3466 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* exit) { |
3455 Label done, heap_number; | 3467 Label deoptimize; |
3456 Register input_reg = ToRegister(instr->InputAt(0)); | 3468 Register input_reg = ToRegister(instr->InputAt(0)); |
3457 | 3469 |
3458 // Heap number map check. | 3470 // Heap number map check. |
3459 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3471 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
3460 factory()->heap_number_map()); | 3472 factory()->heap_number_map()); |
3461 | 3473 |
3462 if (instr->truncating()) { | 3474 if (instr->truncating()) { |
3463 __ j(equal, &heap_number, Label::kNear); | 3475 Label not_heap_number; |
3464 // Check for undefined. Undefined is converted to zero for truncating | |
3465 // conversions. | |
3466 __ cmp(input_reg, factory()->undefined_value()); | |
3467 DeoptimizeIf(not_equal, instr->environment()); | |
3468 __ mov(input_reg, 0); | |
3469 __ jmp(&done, Label::kNear); | |
3470 | 3476 |
3471 __ bind(&heap_number); | 3477 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 3478 |
3472 if (CpuFeatures::IsSupported(SSE3)) { | 3479 if (CpuFeatures::IsSupported(SSE3)) { |
3473 CpuFeatures::Scope scope(SSE3); | 3480 CpuFeatures::Scope scope(SSE3); |
3474 Label convert; | 3481 Label fix_fp_stack_and_deoptimize; |
3475 // Use more powerful conversion when sse3 is available. | 3482 // Use more powerful conversion when sse3 is available. |
3476 // Load x87 register with heap number. | 3483 // Load x87 register with heap number. |
3477 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3484 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3478 // Get exponent alone and check for too-big exponent. | 3485 // Get exponent alone and check for too-big exponent. |
3479 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3486 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
3480 __ and_(input_reg, HeapNumber::kExponentMask); | 3487 __ and_(input_reg, HeapNumber::kExponentMask); |
3481 const uint32_t kTooBigExponent = | 3488 const uint32_t kTooBigExponent = |
3482 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | 3489 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
3483 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); | 3490 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); |
3484 __ j(less, &convert, Label::kNear); | 3491 __ j(greater_equal, &fix_fp_stack_and_deoptimize, Label::kNear); |
3485 // Pop FPU stack before deoptimizing. | |
3486 __ ffree(0); | |
3487 __ fincstp(); | |
3488 DeoptimizeIf(no_condition, instr->environment()); | |
3489 | 3492 |
3490 // Reserve space for 64 bit answer. | 3493 // Reserve space for 64 bit answer. |
3491 __ bind(&convert); | |
3492 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3494 __ sub(Operand(esp), Immediate(kDoubleSize)); |
3493 // Do conversion, which cannot fail because we checked the exponent. | 3495 // Do conversion, which cannot fail because we checked the exponent. |
3494 __ fisttp_d(Operand(esp, 0)); | 3496 __ fisttp_d(Operand(esp, 0)); |
3495 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | 3497 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
3496 __ add(Operand(esp), Immediate(kDoubleSize)); | 3498 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 3499 __ jmp(exit); |
| 3500 |
| 3501 __ bind(&fix_fp_stack_and_deoptimize); |
| 3502 // Pop FPU stack before deoptimizing. |
| 3503 __ ffree(0); |
| 3504 __ fincstp(); |
| 3505 __ jmp(&deoptimize, Label::kNear); |
| 3506 |
3497 } else { | 3507 } else { |
3498 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); | 3508 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
3499 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3509 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3500 __ cvttsd2si(input_reg, Operand(xmm0)); | 3510 __ cvttsd2si(input_reg, Operand(xmm0)); |
3501 __ cmp(input_reg, 0x80000000u); | 3511 __ cmp(input_reg, 0x80000000u); |
3502 __ j(not_equal, &done); | 3512 __ j(equal, exit, Label::kNear); |
3503 // Check if the input was 0x8000000 (kMinInt). | 3513 // Check if the input was 0x8000000 (kMinInt). |
3504 // If no, then we got an overflow and we deoptimize. | 3514 // If no, then we got an overflow and we deoptimize. |
3505 ExternalReference min_int = ExternalReference::address_of_min_int(); | 3515 ExternalReference min_int = ExternalReference::address_of_min_int(); |
3506 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | 3516 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
3507 __ ucomisd(xmm_temp, xmm0); | 3517 __ ucomisd(xmm_temp, xmm0); |
3508 DeoptimizeIf(not_equal, instr->environment()); | 3518 __ j(not_equal, &deoptimize, Label::kNear); |
3509 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3519 __ j(parity_even, &deoptimize, Label::kNear); // NaN. |
| 3520 __ jmp(exit); |
3510 } | 3521 } |
| 3522 |
| 3523 __ bind(¬_heap_number); |
| 3524 // Check for undefined. Undefined is converted to zero for truncating |
| 3525 // conversions. |
| 3526 __ cmp(input_reg, factory()->undefined_value()); |
| 3527 __ j(not_equal, &deoptimize, Label::kNear); |
| 3528 __ Set(input_reg, Immediate(0)); |
| 3529 __ jmp(exit); |
| 3530 |
3511 } else { | 3531 } else { |
3512 // Deoptimize if we don't have a heap number. | 3532 // Deoptimize if we don't have a heap number. |
3513 DeoptimizeIf(not_equal, instr->environment()); | 3533 __ j(not_equal, &deoptimize, Label::kNear); |
3514 | 3534 |
3515 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); | 3535 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
3516 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3536 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3517 __ cvttsd2si(input_reg, Operand(xmm0)); | 3537 __ cvttsd2si(input_reg, Operand(xmm0)); |
3518 __ cvtsi2sd(xmm_temp, Operand(input_reg)); | 3538 __ cvtsi2sd(xmm_temp, Operand(input_reg)); |
3519 __ ucomisd(xmm0, xmm_temp); | 3539 __ ucomisd(xmm0, xmm_temp); |
3520 DeoptimizeIf(not_equal, instr->environment()); | 3540 __ j(not_equal, &deoptimize, Label::kNear); |
3521 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3541 |
3522 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3542 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3543 __ j(parity_even, &deoptimize, Label::kNear); // NaN. |
3523 __ test(input_reg, Operand(input_reg)); | 3544 __ test(input_reg, Operand(input_reg)); |
3524 __ j(not_zero, &done); | 3545 __ j(not_zero, exit); |
3525 __ movmskpd(input_reg, xmm0); | 3546 __ movmskpd(input_reg, xmm0); |
3526 __ and_(input_reg, 1); | 3547 __ and_(input_reg, 1); |
3527 DeoptimizeIf(not_zero, instr->environment()); | 3548 __ j(zero, exit); |
| 3549 } else { |
| 3550 __ j(parity_odd, exit); // Exit if not NaN, fall through if NaN. |
3528 } | 3551 } |
3529 } | 3552 } |
3530 __ bind(&done); | 3553 |
| 3554 __ bind(&deoptimize); |
| 3555 DeoptimizeIf(no_condition, instr->environment()); |
3531 } | 3556 } |
3532 | 3557 |
3533 | 3558 |
3534 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 3559 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
3535 LOperand* input = instr->InputAt(0); | 3560 LOperand* input = instr->InputAt(0); |
3536 ASSERT(input->IsRegister()); | 3561 ASSERT(input->IsRegister()); |
3537 ASSERT(input->Equals(instr->result())); | 3562 ASSERT(input->Equals(instr->result())); |
3538 | 3563 |
3539 Register input_reg = ToRegister(input); | 3564 Register input_reg = ToRegister(input); |
3540 | 3565 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3684 | 3709 |
3685 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3710 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
3686 LOperand* input = instr->InputAt(0); | 3711 LOperand* input = instr->InputAt(0); |
3687 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 3712 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
3688 DeoptimizeIf(not_zero, instr->environment()); | 3713 DeoptimizeIf(not_zero, instr->environment()); |
3689 } | 3714 } |
3690 | 3715 |
3691 | 3716 |
3692 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 3717 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
3693 LOperand* input = instr->InputAt(0); | 3718 LOperand* input = instr->InputAt(0); |
3694 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 3719 if (input->IsRegister()) { |
| 3720 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
| 3721 } else { |
| 3722 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
| 3723 } |
3695 DeoptimizeIf(zero, instr->environment()); | 3724 DeoptimizeIf(zero, instr->environment()); |
3696 } | 3725 } |
3697 | 3726 |
3698 | 3727 |
3699 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3728 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
3700 Register input = ToRegister(instr->InputAt(0)); | 3729 Register input = ToRegister(instr->InputAt(0)); |
3701 Register temp = ToRegister(instr->TempAt(0)); | 3730 Register temp = ToRegister(instr->TempAt(0)); |
3702 | 3731 |
3703 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 3732 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
3704 | 3733 |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3975 __ push(Immediate(pretenure | 4004 __ push(Immediate(pretenure |
3976 ? factory()->true_value() | 4005 ? factory()->true_value() |
3977 : factory()->false_value())); | 4006 : factory()->false_value())); |
3978 CallRuntime(Runtime::kNewClosure, 3, instr, RESTORE_CONTEXT); | 4007 CallRuntime(Runtime::kNewClosure, 3, instr, RESTORE_CONTEXT); |
3979 } | 4008 } |
3980 } | 4009 } |
3981 | 4010 |
3982 | 4011 |
3983 void LCodeGen::DoTypeof(LTypeof* instr) { | 4012 void LCodeGen::DoTypeof(LTypeof* instr) { |
3984 LOperand* input = instr->InputAt(0); | 4013 LOperand* input = instr->InputAt(0); |
3985 if (input->IsConstantOperand()) { | 4014 EmitPush(input); |
3986 __ push(ToImmediate(input)); | |
3987 } else { | |
3988 __ push(ToOperand(input)); | |
3989 } | |
3990 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); | 4015 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); |
3991 } | 4016 } |
3992 | 4017 |
3993 | 4018 |
3994 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4019 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
3995 Register input = ToRegister(instr->InputAt(0)); | 4020 Register input = ToRegister(instr->InputAt(0)); |
3996 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4021 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
3997 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4022 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
3998 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4023 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
3999 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4024 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4106 | 4131 |
4107 | 4132 |
4108 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 4133 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
4109 DeoptimizeIf(no_condition, instr->environment()); | 4134 DeoptimizeIf(no_condition, instr->environment()); |
4110 } | 4135 } |
4111 | 4136 |
4112 | 4137 |
4113 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { | 4138 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { |
4114 LOperand* obj = instr->object(); | 4139 LOperand* obj = instr->object(); |
4115 LOperand* key = instr->key(); | 4140 LOperand* key = instr->key(); |
4116 __ push(ToOperand(obj)); | 4141 EmitPush(obj); |
4117 if (key->IsConstantOperand()) { | 4142 EmitPush(key); |
4118 __ push(ToImmediate(key)); | |
4119 } else { | |
4120 __ push(ToOperand(key)); | |
4121 } | |
4122 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 4143 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
4123 LPointerMap* pointers = instr->pointer_map(); | 4144 LPointerMap* pointers = instr->pointer_map(); |
4124 LEnvironment* env = instr->deoptimization_environment(); | 4145 LEnvironment* env = instr->deoptimization_environment(); |
4125 RecordPosition(pointers->position()); | 4146 RecordPosition(pointers->position()); |
4126 RegisterEnvironmentForDeoptimization(env); | 4147 RegisterEnvironmentForDeoptimization(env); |
4127 // Create safepoint generator that will also ensure enough space in the | 4148 // Create safepoint generator that will also ensure enough space in the |
4128 // reloc info for patching in deoptimization (since this is invoking a | 4149 // reloc info for patching in deoptimization (since this is invoking a |
4129 // builtin) | 4150 // builtin) |
4130 SafepointGenerator safepoint_generator(this, | 4151 SafepointGenerator safepoint_generator(this, |
4131 pointers, | 4152 pointers, |
4132 env->deoptimization_index()); | 4153 env->deoptimization_index()); |
4133 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4154 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4134 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 4155 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
4135 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); | 4156 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); |
4136 } | 4157 } |
4137 | 4158 |
4138 | 4159 |
4139 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 4160 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
4140 PushSafepointRegistersScope scope(this); | 4161 PushSafepointRegistersScope scope(this); |
4141 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr); | 4162 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr); |
4142 } | 4163 } |
4143 | 4164 |
4144 | 4165 |
4145 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4166 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
4146 class DeferredStackCheck: public LDeferredCode { | 4167 class DeferredStackCheck: public LDeferredCode { |
4147 public: | 4168 public: |
4148 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 4169 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
4149 : LDeferredCode(codegen), instr_(instr) { } | 4170 : LDeferredCode(codegen), instr_(instr) { } |
4150 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 4171 virtual void Generate() { |
| 4172 codegen()->DoDeferredStackCheck(instr_); |
| 4173 __ jmp(exit()); |
| 4174 } |
4151 private: | 4175 private: |
4152 LStackCheck* instr_; | 4176 LStackCheck* instr_; |
4153 }; | 4177 }; |
4154 | 4178 |
4155 if (instr->hydrogen()->is_function_entry()) { | 4179 if (instr->hydrogen()->is_function_entry()) { |
4156 // Perform stack overflow check. | 4180 // Perform stack overflow check. |
4157 Label done; | 4181 Label done; |
4158 ExternalReference stack_limit = | 4182 ExternalReference stack_limit = |
4159 ExternalReference::address_of_stack_limit(isolate()); | 4183 ExternalReference::address_of_stack_limit(isolate()); |
4160 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 4184 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
(...skipping 30 matching lines...) Expand all Loading... |
4191 ASSERT(!environment->HasBeenRegistered()); | 4215 ASSERT(!environment->HasBeenRegistered()); |
4192 RegisterEnvironmentForDeoptimization(environment); | 4216 RegisterEnvironmentForDeoptimization(environment); |
4193 ASSERT(osr_pc_offset_ == -1); | 4217 ASSERT(osr_pc_offset_ == -1); |
4194 osr_pc_offset_ = masm()->pc_offset(); | 4218 osr_pc_offset_ = masm()->pc_offset(); |
4195 } | 4219 } |
4196 | 4220 |
4197 | 4221 |
4198 void LCodeGen::DoIn(LIn* instr) { | 4222 void LCodeGen::DoIn(LIn* instr) { |
4199 LOperand* obj = instr->object(); | 4223 LOperand* obj = instr->object(); |
4200 LOperand* key = instr->key(); | 4224 LOperand* key = instr->key(); |
4201 if (key->IsConstantOperand()) { | 4225 EmitPush(key); |
4202 __ push(ToImmediate(key)); | 4226 EmitPush(obj); |
4203 } else { | |
4204 __ push(ToOperand(key)); | |
4205 } | |
4206 if (obj->IsConstantOperand()) { | |
4207 __ push(ToImmediate(obj)); | |
4208 } else { | |
4209 __ push(ToOperand(obj)); | |
4210 } | |
4211 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 4227 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
4212 LPointerMap* pointers = instr->pointer_map(); | 4228 LPointerMap* pointers = instr->pointer_map(); |
4213 LEnvironment* env = instr->deoptimization_environment(); | 4229 LEnvironment* env = instr->deoptimization_environment(); |
4214 RecordPosition(pointers->position()); | 4230 RecordPosition(pointers->position()); |
4215 RegisterEnvironmentForDeoptimization(env); | 4231 RegisterEnvironmentForDeoptimization(env); |
4216 // Create safepoint generator that will also ensure enough space in the | 4232 // Create safepoint generator that will also ensure enough space in the |
4217 // reloc info for patching in deoptimization (since this is invoking a | 4233 // reloc info for patching in deoptimization (since this is invoking a |
4218 // builtin) | 4234 // builtin) |
4219 SafepointGenerator safepoint_generator(this, | 4235 SafepointGenerator safepoint_generator(this, |
4220 pointers, | 4236 pointers, |
4221 env->deoptimization_index()); | 4237 env->deoptimization_index()); |
4222 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4238 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4223 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4239 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4224 } | 4240 } |
4225 | 4241 |
4226 | 4242 |
4227 #undef __ | 4243 #undef __ |
4228 | 4244 |
4229 } } // namespace v8::internal | 4245 } } // namespace v8::internal |
4230 | 4246 |
4231 #endif // V8_TARGET_ARCH_IA32 | 4247 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |