| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 21 matching lines...) Expand all Loading... |
| 32 #include "x64/lithium-codegen-x64.h" | 32 #include "x64/lithium-codegen-x64.h" |
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
| 34 #include "stub-cache.h" | 34 #include "stub-cache.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 | 39 |
| 40 // When invoking builtins, we need to record the safepoint in the middle of | 40 // When invoking builtins, we need to record the safepoint in the middle of |
| 41 // the invoke instruction sequence generated by the macro assembler. | 41 // the invoke instruction sequence generated by the macro assembler. |
| 42 class SafepointGenerator : public CallWrapper { | 42 class SafepointGenerator V8_FINAL : public CallWrapper { |
| 43 public: | 43 public: |
| 44 SafepointGenerator(LCodeGen* codegen, | 44 SafepointGenerator(LCodeGen* codegen, |
| 45 LPointerMap* pointers, | 45 LPointerMap* pointers, |
| 46 Safepoint::DeoptMode mode) | 46 Safepoint::DeoptMode mode) |
| 47 : codegen_(codegen), | 47 : codegen_(codegen), |
| 48 pointers_(pointers), | 48 pointers_(pointers), |
| 49 deopt_mode_(mode) { } | 49 deopt_mode_(mode) { } |
| 50 virtual ~SafepointGenerator() { } | 50 virtual ~SafepointGenerator() {} |
| 51 | 51 |
| 52 virtual void BeforeCall(int call_size) const { | 52 virtual void BeforeCall(int call_size) const V8_OVERRIDE { |
| 53 codegen_->EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - call_size); | 53 codegen_->EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - call_size); |
| 54 } | 54 } |
| 55 | 55 |
| 56 virtual void AfterCall() const { | 56 virtual void AfterCall() const V8_OVERRIDE { |
| 57 codegen_->RecordSafepoint(pointers_, deopt_mode_); | 57 codegen_->RecordSafepoint(pointers_, deopt_mode_); |
| 58 } | 58 } |
| 59 | 59 |
| 60 private: | 60 private: |
| 61 LCodeGen* codegen_; | 61 LCodeGen* codegen_; |
| 62 LPointerMap* pointers_; | 62 LPointerMap* pointers_; |
| 63 Safepoint::DeoptMode deopt_mode_; | 63 Safepoint::DeoptMode deopt_mode_; |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 | 66 |
| (...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 power = WhichPowerOf2(-divisor); | 1209 power = WhichPowerOf2(-divisor); |
| 1210 } | 1210 } |
| 1211 | 1211 |
| 1212 if (test_value != 0) { | 1212 if (test_value != 0) { |
| 1213 if (instr->hydrogen()->CheckFlag( | 1213 if (instr->hydrogen()->CheckFlag( |
| 1214 HInstruction::kAllUsesTruncatingToInt32)) { | 1214 HInstruction::kAllUsesTruncatingToInt32)) { |
| 1215 Label done, negative; | 1215 Label done, negative; |
| 1216 __ cmpl(dividend, Immediate(0)); | 1216 __ cmpl(dividend, Immediate(0)); |
| 1217 __ j(less, &negative, Label::kNear); | 1217 __ j(less, &negative, Label::kNear); |
| 1218 __ sarl(dividend, Immediate(power)); | 1218 __ sarl(dividend, Immediate(power)); |
| 1219 if (divisor < 0) __ negl(dividend); |
| 1219 __ jmp(&done, Label::kNear); | 1220 __ jmp(&done, Label::kNear); |
| 1220 | 1221 |
| 1221 __ bind(&negative); | 1222 __ bind(&negative); |
| 1222 __ negl(dividend); | 1223 __ negl(dividend); |
| 1223 __ sarl(dividend, Immediate(power)); | 1224 __ sarl(dividend, Immediate(power)); |
| 1224 if (divisor > 0) __ negl(dividend); | 1225 if (divisor > 0) __ negl(dividend); |
| 1225 __ bind(&done); | 1226 __ bind(&done); |
| 1226 return; // Don't fall through to "__ neg" below. | 1227 return; // Don't fall through to "__ neg" below. |
| 1227 } else { | 1228 } else { |
| 1228 // Deoptimize if remainder is not 0. | 1229 // Deoptimize if remainder is not 0. |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1894 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 1894 } else { | 1895 } else { |
| 1895 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1896 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 1896 if (cc != always) { | 1897 if (cc != always) { |
| 1897 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 1898 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
| 1898 } | 1899 } |
| 1899 } | 1900 } |
| 1900 } | 1901 } |
| 1901 | 1902 |
| 1902 | 1903 |
| 1904 template<class InstrType> |
| 1905 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { |
| 1906 int false_block = instr->FalseDestination(chunk_); |
| 1907 __ j(cc, chunk_->GetAssemblyLabel(false_block)); |
| 1908 } |
| 1909 |
| 1910 |
| 1903 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 1911 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 1904 __ int3(); | 1912 __ int3(); |
| 1905 } | 1913 } |
| 1906 | 1914 |
| 1907 | 1915 |
| 1908 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { | 1916 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 1909 Representation r = instr->hydrogen()->value()->representation(); | 1917 Representation r = instr->hydrogen()->value()->representation(); |
| 1910 if (r.IsSmiOrInteger32() || r.IsDouble()) { | 1918 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 1911 EmitBranch(instr, no_condition); | 1919 EmitBranch(instr, no_condition); |
| 1912 } else { | 1920 } else { |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2166 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2174 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
| 2167 __ CmpObject(left, right); | 2175 __ CmpObject(left, right); |
| 2168 } else { | 2176 } else { |
| 2169 Register right = ToRegister(instr->right()); | 2177 Register right = ToRegister(instr->right()); |
| 2170 __ cmpq(left, right); | 2178 __ cmpq(left, right); |
| 2171 } | 2179 } |
| 2172 EmitBranch(instr, equal); | 2180 EmitBranch(instr, equal); |
| 2173 } | 2181 } |
| 2174 | 2182 |
| 2175 | 2183 |
| 2184 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { |
| 2185 if (instr->hydrogen()->representation().IsTagged()) { |
| 2186 Register input_reg = ToRegister(instr->object()); |
| 2187 __ Cmp(input_reg, factory()->the_hole_value()); |
| 2188 EmitBranch(instr, equal); |
| 2189 return; |
| 2190 } |
| 2191 |
| 2192 XMMRegister input_reg = ToDoubleRegister(instr->object()); |
| 2193 __ ucomisd(input_reg, input_reg); |
| 2194 EmitFalseBranch(instr, parity_odd); |
| 2195 |
| 2196 __ subq(rsp, Immediate(kDoubleSize)); |
| 2197 __ movsd(MemOperand(rsp, 0), input_reg); |
| 2198 __ addq(rsp, Immediate(kDoubleSize)); |
| 2199 |
| 2200 int offset = sizeof(kHoleNanUpper32); |
| 2201 __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32)); |
| 2202 EmitBranch(instr, equal); |
| 2203 } |
| 2204 |
| 2205 |
| 2176 Condition LCodeGen::EmitIsObject(Register input, | 2206 Condition LCodeGen::EmitIsObject(Register input, |
| 2177 Label* is_not_object, | 2207 Label* is_not_object, |
| 2178 Label* is_object) { | 2208 Label* is_object) { |
| 2179 ASSERT(!input.is(kScratchRegister)); | 2209 ASSERT(!input.is(kScratchRegister)); |
| 2180 | 2210 |
| 2181 __ JumpIfSmi(input, is_not_object); | 2211 __ JumpIfSmi(input, is_not_object); |
| 2182 | 2212 |
| 2183 __ CompareRoot(input, Heap::kNullValueRootIndex); | 2213 __ CompareRoot(input, Heap::kNullValueRootIndex); |
| 2184 __ j(equal, is_object); | 2214 __ j(equal, is_object); |
| 2185 | 2215 |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2430 __ j(zero, &true_value, Label::kNear); | 2460 __ j(zero, &true_value, Label::kNear); |
| 2431 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2461 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 2432 __ jmp(&done, Label::kNear); | 2462 __ jmp(&done, Label::kNear); |
| 2433 __ bind(&true_value); | 2463 __ bind(&true_value); |
| 2434 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2464 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
| 2435 __ bind(&done); | 2465 __ bind(&done); |
| 2436 } | 2466 } |
| 2437 | 2467 |
| 2438 | 2468 |
| 2439 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2469 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 2440 class DeferredInstanceOfKnownGlobal: public LDeferredCode { | 2470 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { |
| 2441 public: | 2471 public: |
| 2442 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2472 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| 2443 LInstanceOfKnownGlobal* instr) | 2473 LInstanceOfKnownGlobal* instr) |
| 2444 : LDeferredCode(codegen), instr_(instr) { } | 2474 : LDeferredCode(codegen), instr_(instr) { } |
| 2445 virtual void Generate() { | 2475 virtual void Generate() V8_OVERRIDE { |
| 2446 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); | 2476 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); |
| 2447 } | 2477 } |
| 2448 virtual LInstruction* instr() { return instr_; } | 2478 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 2449 Label* map_check() { return &map_check_; } | 2479 Label* map_check() { return &map_check_; } |
| 2450 private: | 2480 private: |
| 2451 LInstanceOfKnownGlobal* instr_; | 2481 LInstanceOfKnownGlobal* instr_; |
| 2452 Label map_check_; | 2482 Label map_check_; |
| 2453 }; | 2483 }; |
| 2454 | 2484 |
| 2455 | 2485 |
| 2456 DeferredInstanceOfKnownGlobal* deferred; | 2486 DeferredInstanceOfKnownGlobal* deferred; |
| 2457 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2487 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
| 2458 | 2488 |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2757 Register result = ToRegister(instr->result()); | 2787 Register result = ToRegister(instr->result()); |
| 2758 if (access.IsInobject()) { | 2788 if (access.IsInobject()) { |
| 2759 __ movq(result, FieldOperand(object, offset)); | 2789 __ movq(result, FieldOperand(object, offset)); |
| 2760 } else { | 2790 } else { |
| 2761 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2791 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2762 __ movq(result, FieldOperand(result, offset)); | 2792 __ movq(result, FieldOperand(result, offset)); |
| 2763 } | 2793 } |
| 2764 } | 2794 } |
| 2765 | 2795 |
| 2766 | 2796 |
| 2767 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, | |
| 2768 Register object, | |
| 2769 Handle<Map> type, | |
| 2770 Handle<String> name, | |
| 2771 LEnvironment* env) { | |
| 2772 LookupResult lookup(isolate()); | |
| 2773 type->LookupDescriptor(NULL, *name, &lookup); | |
| 2774 ASSERT(lookup.IsFound() || lookup.IsCacheable()); | |
| 2775 if (lookup.IsField()) { | |
| 2776 int index = lookup.GetLocalFieldIndexFromMap(*type); | |
| 2777 int offset = index * kPointerSize; | |
| 2778 if (index < 0) { | |
| 2779 // Negative property indices are in-object properties, indexed | |
| 2780 // from the end of the fixed part of the object. | |
| 2781 __ movq(result, FieldOperand(object, offset + type->instance_size())); | |
| 2782 } else { | |
| 2783 // Non-negative property indices are in the properties array. | |
| 2784 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | |
| 2785 __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); | |
| 2786 } | |
| 2787 } else if (lookup.IsConstant()) { | |
| 2788 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate()); | |
| 2789 __ LoadObject(result, constant); | |
| 2790 } else { | |
| 2791 // Negative lookup. | |
| 2792 // Check prototypes. | |
| 2793 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); | |
| 2794 Heap* heap = type->GetHeap(); | |
| 2795 while (*current != heap->null_value()) { | |
| 2796 __ LoadHeapObject(result, current); | |
| 2797 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), | |
| 2798 Handle<Map>(current->map())); | |
| 2799 DeoptimizeIf(not_equal, env); | |
| 2800 current = | |
| 2801 Handle<HeapObject>(HeapObject::cast(current->map()->prototype())); | |
| 2802 } | |
| 2803 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | |
| 2804 } | |
| 2805 } | |
| 2806 | |
| 2807 | |
| 2808 // Check for cases where EmitLoadFieldOrConstantFunction needs to walk the | |
| 2809 // prototype chain, which causes unbounded code generation. | |
| 2810 static bool CompactEmit(SmallMapList* list, | |
| 2811 Handle<String> name, | |
| 2812 int i, | |
| 2813 Isolate* isolate) { | |
| 2814 Handle<Map> map = list->at(i); | |
| 2815 LookupResult lookup(isolate); | |
| 2816 map->LookupDescriptor(NULL, *name, &lookup); | |
| 2817 return lookup.IsField() || lookup.IsConstant(); | |
| 2818 } | |
| 2819 | |
| 2820 | |
| 2821 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | |
| 2822 Register object = ToRegister(instr->object()); | |
| 2823 Register result = ToRegister(instr->result()); | |
| 2824 | |
| 2825 int map_count = instr->hydrogen()->types()->length(); | |
| 2826 bool need_generic = instr->hydrogen()->need_generic(); | |
| 2827 | |
| 2828 if (map_count == 0 && !need_generic) { | |
| 2829 DeoptimizeIf(no_condition, instr->environment()); | |
| 2830 return; | |
| 2831 } | |
| 2832 Handle<String> name = instr->hydrogen()->name(); | |
| 2833 Label done; | |
| 2834 bool all_are_compact = true; | |
| 2835 for (int i = 0; i < map_count; ++i) { | |
| 2836 if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) { | |
| 2837 all_are_compact = false; | |
| 2838 break; | |
| 2839 } | |
| 2840 } | |
| 2841 for (int i = 0; i < map_count; ++i) { | |
| 2842 bool last = (i == map_count - 1); | |
| 2843 Handle<Map> map = instr->hydrogen()->types()->at(i); | |
| 2844 Label check_passed; | |
| 2845 __ CompareMap(object, map, &check_passed); | |
| 2846 if (last && !need_generic) { | |
| 2847 DeoptimizeIf(not_equal, instr->environment()); | |
| 2848 __ bind(&check_passed); | |
| 2849 EmitLoadFieldOrConstantFunction( | |
| 2850 result, object, map, name, instr->environment()); | |
| 2851 } else { | |
| 2852 Label next; | |
| 2853 bool compact = all_are_compact ? true : | |
| 2854 CompactEmit(instr->hydrogen()->types(), name, i, isolate()); | |
| 2855 __ j(not_equal, &next, compact ? Label::kNear : Label::kFar); | |
| 2856 __ bind(&check_passed); | |
| 2857 EmitLoadFieldOrConstantFunction( | |
| 2858 result, object, map, name, instr->environment()); | |
| 2859 __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar); | |
| 2860 __ bind(&next); | |
| 2861 } | |
| 2862 } | |
| 2863 if (need_generic) { | |
| 2864 __ Move(rcx, name); | |
| 2865 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 2866 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 2867 } | |
| 2868 __ bind(&done); | |
| 2869 } | |
| 2870 | |
| 2871 | |
| 2872 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2797 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 2873 ASSERT(ToRegister(instr->object()).is(rax)); | 2798 ASSERT(ToRegister(instr->object()).is(rax)); |
| 2874 ASSERT(ToRegister(instr->result()).is(rax)); | 2799 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2875 | 2800 |
| 2876 __ Move(rcx, instr->name()); | 2801 __ Move(rcx, instr->name()); |
| 2877 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2802 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2878 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2803 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2879 } | 2804 } |
| 2880 | 2805 |
| 2881 | 2806 |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3469 Label is_positive; | 3394 Label is_positive; |
| 3470 __ j(not_sign, &is_positive, Label::kNear); | 3395 __ j(not_sign, &is_positive, Label::kNear); |
| 3471 __ neg(input_reg); // Sets flags. | 3396 __ neg(input_reg); // Sets flags. |
| 3472 DeoptimizeIf(negative, instr->environment()); | 3397 DeoptimizeIf(negative, instr->environment()); |
| 3473 __ bind(&is_positive); | 3398 __ bind(&is_positive); |
| 3474 } | 3399 } |
| 3475 | 3400 |
| 3476 | 3401 |
| 3477 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3402 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3478 // Class for deferred case. | 3403 // Class for deferred case. |
| 3479 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3404 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { |
| 3480 public: | 3405 public: |
| 3481 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3406 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| 3482 : LDeferredCode(codegen), instr_(instr) { } | 3407 : LDeferredCode(codegen), instr_(instr) { } |
| 3483 virtual void Generate() { | 3408 virtual void Generate() V8_OVERRIDE { |
| 3484 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3409 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3485 } | 3410 } |
| 3486 virtual LInstruction* instr() { return instr_; } | 3411 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3487 private: | 3412 private: |
| 3488 LMathAbs* instr_; | 3413 LMathAbs* instr_; |
| 3489 }; | 3414 }; |
| 3490 | 3415 |
| 3491 ASSERT(instr->value()->Equals(instr->result())); | 3416 ASSERT(instr->value()->Equals(instr->result())); |
| 3492 Representation r = instr->hydrogen()->value()->representation(); | 3417 Representation r = instr->hydrogen()->value()->representation(); |
| 3493 | 3418 |
| 3494 if (r.IsDouble()) { | 3419 if (r.IsDouble()) { |
| 3495 XMMRegister scratch = xmm0; | 3420 XMMRegister scratch = xmm0; |
| 3496 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3421 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3701 __ CallStub(&stub); | 3626 __ CallStub(&stub); |
| 3702 } else { | 3627 } else { |
| 3703 ASSERT(exponent_type.IsDouble()); | 3628 ASSERT(exponent_type.IsDouble()); |
| 3704 MathPowStub stub(MathPowStub::DOUBLE); | 3629 MathPowStub stub(MathPowStub::DOUBLE); |
| 3705 __ CallStub(&stub); | 3630 __ CallStub(&stub); |
| 3706 } | 3631 } |
| 3707 } | 3632 } |
| 3708 | 3633 |
| 3709 | 3634 |
| 3710 void LCodeGen::DoRandom(LRandom* instr) { | 3635 void LCodeGen::DoRandom(LRandom* instr) { |
| 3711 class DeferredDoRandom: public LDeferredCode { | 3636 class DeferredDoRandom V8_FINAL : public LDeferredCode { |
| 3712 public: | 3637 public: |
| 3713 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) | 3638 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) |
| 3714 : LDeferredCode(codegen), instr_(instr) { } | 3639 : LDeferredCode(codegen), instr_(instr) { } |
| 3715 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } | 3640 virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredRandom(instr_); } |
| 3716 virtual LInstruction* instr() { return instr_; } | 3641 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3717 private: | 3642 private: |
| 3718 LRandom* instr_; | 3643 LRandom* instr_; |
| 3719 }; | 3644 }; |
| 3720 | 3645 |
| 3721 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3646 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
| 3722 | 3647 |
| 3723 // Having marked this instruction as a call we can use any | 3648 // Having marked this instruction as a call we can use any |
| 3724 // registers. | 3649 // registers. |
| 3725 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3650 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3726 | 3651 |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4391 | 4316 |
| 4392 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4317 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4393 EmitPushTaggedOperand(instr->left()); | 4318 EmitPushTaggedOperand(instr->left()); |
| 4394 EmitPushTaggedOperand(instr->right()); | 4319 EmitPushTaggedOperand(instr->right()); |
| 4395 StringAddStub stub(instr->hydrogen()->flags()); | 4320 StringAddStub stub(instr->hydrogen()->flags()); |
| 4396 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4321 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4397 } | 4322 } |
| 4398 | 4323 |
| 4399 | 4324 |
| 4400 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4325 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4401 class DeferredStringCharCodeAt: public LDeferredCode { | 4326 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4402 public: | 4327 public: |
| 4403 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4328 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4404 : LDeferredCode(codegen), instr_(instr) { } | 4329 : LDeferredCode(codegen), instr_(instr) { } |
| 4405 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 4330 virtual void Generate() V8_OVERRIDE { |
| 4406 virtual LInstruction* instr() { return instr_; } | 4331 codegen()->DoDeferredStringCharCodeAt(instr_); |
| 4332 } |
| 4333 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4407 private: | 4334 private: |
| 4408 LStringCharCodeAt* instr_; | 4335 LStringCharCodeAt* instr_; |
| 4409 }; | 4336 }; |
| 4410 | 4337 |
| 4411 DeferredStringCharCodeAt* deferred = | 4338 DeferredStringCharCodeAt* deferred = |
| 4412 new(zone()) DeferredStringCharCodeAt(this, instr); | 4339 new(zone()) DeferredStringCharCodeAt(this, instr); |
| 4413 | 4340 |
| 4414 StringCharLoadGenerator::Generate(masm(), | 4341 StringCharLoadGenerator::Generate(masm(), |
| 4415 ToRegister(instr->string()), | 4342 ToRegister(instr->string()), |
| 4416 ToRegister(instr->index()), | 4343 ToRegister(instr->index()), |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4443 __ push(index); | 4370 __ push(index); |
| 4444 } | 4371 } |
| 4445 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4372 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
| 4446 __ AssertSmi(rax); | 4373 __ AssertSmi(rax); |
| 4447 __ SmiToInteger32(rax, rax); | 4374 __ SmiToInteger32(rax, rax); |
| 4448 __ StoreToSafepointRegisterSlot(result, rax); | 4375 __ StoreToSafepointRegisterSlot(result, rax); |
| 4449 } | 4376 } |
| 4450 | 4377 |
| 4451 | 4378 |
| 4452 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4379 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 4453 class DeferredStringCharFromCode: public LDeferredCode { | 4380 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { |
| 4454 public: | 4381 public: |
| 4455 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 4382 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| 4456 : LDeferredCode(codegen), instr_(instr) { } | 4383 : LDeferredCode(codegen), instr_(instr) { } |
| 4457 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 4384 virtual void Generate() V8_OVERRIDE { |
| 4458 virtual LInstruction* instr() { return instr_; } | 4385 codegen()->DoDeferredStringCharFromCode(instr_); |
| 4386 } |
| 4387 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4459 private: | 4388 private: |
| 4460 LStringCharFromCode* instr_; | 4389 LStringCharFromCode* instr_; |
| 4461 }; | 4390 }; |
| 4462 | 4391 |
| 4463 DeferredStringCharFromCode* deferred = | 4392 DeferredStringCharFromCode* deferred = |
| 4464 new(zone()) DeferredStringCharFromCode(this, instr); | 4393 new(zone()) DeferredStringCharFromCode(this, instr); |
| 4465 | 4394 |
| 4466 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 4395 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 4467 Register char_code = ToRegister(instr->char_code()); | 4396 Register char_code = ToRegister(instr->char_code()); |
| 4468 Register result = ToRegister(instr->result()); | 4397 Register result = ToRegister(instr->result()); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4537 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4466 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4538 LOperand* input = instr->value(); | 4467 LOperand* input = instr->value(); |
| 4539 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4468 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4540 Register reg = ToRegister(input); | 4469 Register reg = ToRegister(input); |
| 4541 | 4470 |
| 4542 __ Integer32ToSmi(reg, reg); | 4471 __ Integer32ToSmi(reg, reg); |
| 4543 } | 4472 } |
| 4544 | 4473 |
| 4545 | 4474 |
| 4546 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4475 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| 4547 class DeferredNumberTagU: public LDeferredCode { | 4476 class DeferredNumberTagU V8_FINAL : public LDeferredCode { |
| 4548 public: | 4477 public: |
| 4549 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4478 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
| 4550 : LDeferredCode(codegen), instr_(instr) { } | 4479 : LDeferredCode(codegen), instr_(instr) { } |
| 4551 virtual void Generate() { | 4480 virtual void Generate() V8_OVERRIDE { |
| 4552 codegen()->DoDeferredNumberTagU(instr_); | 4481 codegen()->DoDeferredNumberTagU(instr_); |
| 4553 } | 4482 } |
| 4554 virtual LInstruction* instr() { return instr_; } | 4483 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4555 private: | 4484 private: |
| 4556 LNumberTagU* instr_; | 4485 LNumberTagU* instr_; |
| 4557 }; | 4486 }; |
| 4558 | 4487 |
| 4559 LOperand* input = instr->value(); | 4488 LOperand* input = instr->value(); |
| 4560 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4489 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4561 Register reg = ToRegister(input); | 4490 Register reg = ToRegister(input); |
| 4562 | 4491 |
| 4563 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4492 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
| 4564 __ cmpl(reg, Immediate(Smi::kMaxValue)); | 4493 __ cmpl(reg, Immediate(Smi::kMaxValue)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4600 | 4529 |
| 4601 // Done. Put the value in xmm1 into the value of the allocated heap | 4530 // Done. Put the value in xmm1 into the value of the allocated heap |
| 4602 // number. | 4531 // number. |
| 4603 __ bind(&done); | 4532 __ bind(&done); |
| 4604 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm1); | 4533 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm1); |
| 4605 __ StoreToSafepointRegisterSlot(reg, reg); | 4534 __ StoreToSafepointRegisterSlot(reg, reg); |
| 4606 } | 4535 } |
| 4607 | 4536 |
| 4608 | 4537 |
| 4609 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4538 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 4610 class DeferredNumberTagD: public LDeferredCode { | 4539 class DeferredNumberTagD V8_FINAL : public LDeferredCode { |
| 4611 public: | 4540 public: |
| 4612 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4541 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 4613 : LDeferredCode(codegen), instr_(instr) { } | 4542 : LDeferredCode(codegen), instr_(instr) { } |
| 4614 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4543 virtual void Generate() V8_OVERRIDE { |
| 4615 virtual LInstruction* instr() { return instr_; } | 4544 codegen()->DoDeferredNumberTagD(instr_); |
| 4545 } |
| 4546 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4616 private: | 4547 private: |
| 4617 LNumberTagD* instr_; | 4548 LNumberTagD* instr_; |
| 4618 }; | 4549 }; |
| 4619 | 4550 |
| 4620 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4551 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4621 Register reg = ToRegister(instr->result()); | 4552 Register reg = ToRegister(instr->result()); |
| 4622 Register tmp = ToRegister(instr->temp()); | 4553 Register tmp = ToRegister(instr->temp()); |
| 4623 | 4554 |
| 4624 bool convert_hole = false; | |
| 4625 HValue* change_input = instr->hydrogen()->value(); | |
| 4626 if (change_input->IsLoadKeyed()) { | |
| 4627 HLoadKeyed* load = HLoadKeyed::cast(change_input); | |
| 4628 convert_hole = load->UsesMustHandleHole(); | |
| 4629 } | |
| 4630 | |
| 4631 Label no_special_nan_handling; | |
| 4632 Label done; | |
| 4633 if (convert_hole) { | |
| 4634 XMMRegister input_reg = ToDoubleRegister(instr->value()); | |
| 4635 __ ucomisd(input_reg, input_reg); | |
| 4636 __ j(parity_odd, &no_special_nan_handling); | |
| 4637 __ subq(rsp, Immediate(kDoubleSize)); | |
| 4638 __ movsd(MemOperand(rsp, 0), input_reg); | |
| 4639 __ cmpl(MemOperand(rsp, sizeof(kHoleNanLower32)), | |
| 4640 Immediate(kHoleNanUpper32)); | |
| 4641 Label canonicalize; | |
| 4642 __ j(not_equal, &canonicalize); | |
| 4643 __ addq(rsp, Immediate(kDoubleSize)); | |
| 4644 __ Move(reg, factory()->the_hole_value()); | |
| 4645 __ jmp(&done); | |
| 4646 __ bind(&canonicalize); | |
| 4647 __ addq(rsp, Immediate(kDoubleSize)); | |
| 4648 __ Set(kScratchRegister, BitCast<uint64_t>( | |
| 4649 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); | |
| 4650 __ movq(input_reg, kScratchRegister); | |
| 4651 } | |
| 4652 | |
| 4653 __ bind(&no_special_nan_handling); | |
| 4654 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4555 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4655 if (FLAG_inline_new) { | 4556 if (FLAG_inline_new) { |
| 4656 __ AllocateHeapNumber(reg, tmp, deferred->entry()); | 4557 __ AllocateHeapNumber(reg, tmp, deferred->entry()); |
| 4657 } else { | 4558 } else { |
| 4658 __ jmp(deferred->entry()); | 4559 __ jmp(deferred->entry()); |
| 4659 } | 4560 } |
| 4660 __ bind(deferred->exit()); | 4561 __ bind(deferred->exit()); |
| 4661 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 4562 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
| 4662 | |
| 4663 __ bind(&done); | |
| 4664 } | 4563 } |
| 4665 | 4564 |
| 4666 | 4565 |
| 4667 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4566 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4668 // TODO(3095996): Get rid of this. For now, we need to make the | 4567 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4669 // result register contain a valid pointer because it is already | 4568 // result register contain a valid pointer because it is already |
| 4670 // contained in the register pointer map. | 4569 // contained in the register pointer map. |
| 4671 Register reg = ToRegister(instr->result()); | 4570 Register reg = ToRegister(instr->result()); |
| 4672 __ Move(reg, Smi::FromInt(0)); | 4571 __ Move(reg, Smi::FromInt(0)); |
| 4673 | 4572 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4697 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 4596 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
| 4698 } else { | 4597 } else { |
| 4699 __ AssertSmi(input); | 4598 __ AssertSmi(input); |
| 4700 } | 4599 } |
| 4701 __ SmiToInteger32(input, input); | 4600 __ SmiToInteger32(input, input); |
| 4702 } | 4601 } |
| 4703 | 4602 |
| 4704 | 4603 |
| 4705 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4604 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 4706 XMMRegister result_reg, | 4605 XMMRegister result_reg, |
| 4707 bool allow_undefined_as_nan, | 4606 bool can_convert_undefined_to_nan, |
| 4708 bool deoptimize_on_minus_zero, | 4607 bool deoptimize_on_minus_zero, |
| 4709 LEnvironment* env, | 4608 LEnvironment* env, |
| 4710 NumberUntagDMode mode) { | 4609 NumberUntagDMode mode) { |
| 4711 Label load_smi, done; | 4610 Label load_smi, done; |
| 4712 | 4611 |
| 4713 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > | 4612 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4714 NUMBER_CANDIDATE_IS_ANY_TAGGED); | |
| 4715 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { | |
| 4716 // Smi check. | 4613 // Smi check. |
| 4717 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 4614 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
| 4718 | 4615 |
| 4719 // Heap number map check. | 4616 // Heap number map check. |
| 4720 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4617 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4721 Heap::kHeapNumberMapRootIndex); | 4618 Heap::kHeapNumberMapRootIndex); |
| 4722 if (!allow_undefined_as_nan) { | 4619 if (!can_convert_undefined_to_nan) { |
| 4723 DeoptimizeIf(not_equal, env); | 4620 DeoptimizeIf(not_equal, env); |
| 4724 } else { | 4621 } else { |
| 4725 Label heap_number, convert; | 4622 Label heap_number, convert; |
| 4726 __ j(equal, &heap_number, Label::kNear); | 4623 __ j(equal, &heap_number, Label::kNear); |
| 4727 | 4624 |
| 4728 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. | 4625 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. |
| 4729 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4626 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
| 4730 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) { | |
| 4731 __ j(equal, &convert, Label::kNear); | |
| 4732 __ CompareRoot(input_reg, Heap::kTheHoleValueRootIndex); | |
| 4733 } | |
| 4734 DeoptimizeIf(not_equal, env); | 4627 DeoptimizeIf(not_equal, env); |
| 4735 | 4628 |
| 4736 __ bind(&convert); | 4629 __ bind(&convert); |
| 4737 __ xorps(result_reg, result_reg); | 4630 __ xorps(result_reg, result_reg); |
| 4738 __ divsd(result_reg, result_reg); | 4631 __ divsd(result_reg, result_reg); |
| 4739 __ jmp(&done, Label::kNear); | 4632 __ jmp(&done, Label::kNear); |
| 4740 | 4633 |
| 4741 __ bind(&heap_number); | 4634 __ bind(&heap_number); |
| 4742 } | 4635 } |
| 4743 // Heap number to XMM conversion. | 4636 // Heap number to XMM conversion. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4805 __ movmskpd(input_reg, xmm0); | 4698 __ movmskpd(input_reg, xmm0); |
| 4806 __ andl(input_reg, Immediate(1)); | 4699 __ andl(input_reg, Immediate(1)); |
| 4807 DeoptimizeIf(not_zero, instr->environment()); | 4700 DeoptimizeIf(not_zero, instr->environment()); |
| 4808 } | 4701 } |
| 4809 } | 4702 } |
| 4810 __ bind(&done); | 4703 __ bind(&done); |
| 4811 } | 4704 } |
| 4812 | 4705 |
| 4813 | 4706 |
| 4814 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4707 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 4815 class DeferredTaggedToI: public LDeferredCode { | 4708 class DeferredTaggedToI V8_FINAL : public LDeferredCode { |
| 4816 public: | 4709 public: |
| 4817 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4710 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 4818 : LDeferredCode(codegen), instr_(instr) { } | 4711 : LDeferredCode(codegen), instr_(instr) { } |
| 4819 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4712 virtual void Generate() V8_OVERRIDE { |
| 4820 virtual LInstruction* instr() { return instr_; } | 4713 codegen()->DoDeferredTaggedToI(instr_); |
| 4714 } |
| 4715 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4821 private: | 4716 private: |
| 4822 LTaggedToI* instr_; | 4717 LTaggedToI* instr_; |
| 4823 }; | 4718 }; |
| 4824 | 4719 |
| 4825 LOperand* input = instr->value(); | 4720 LOperand* input = instr->value(); |
| 4826 ASSERT(input->IsRegister()); | 4721 ASSERT(input->IsRegister()); |
| 4827 ASSERT(input->Equals(instr->result())); | 4722 ASSERT(input->Equals(instr->result())); |
| 4828 | 4723 |
| 4829 Register input_reg = ToRegister(input); | 4724 Register input_reg = ToRegister(input); |
| 4830 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4725 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
| 4831 __ JumpIfNotSmi(input_reg, deferred->entry()); | 4726 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 4832 __ SmiToInteger32(input_reg, input_reg); | 4727 __ SmiToInteger32(input_reg, input_reg); |
| 4833 __ bind(deferred->exit()); | 4728 __ bind(deferred->exit()); |
| 4834 } | 4729 } |
| 4835 | 4730 |
| 4836 | 4731 |
| 4837 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4732 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 4838 LOperand* input = instr->value(); | 4733 LOperand* input = instr->value(); |
| 4839 ASSERT(input->IsRegister()); | 4734 ASSERT(input->IsRegister()); |
| 4840 LOperand* result = instr->result(); | 4735 LOperand* result = instr->result(); |
| 4841 ASSERT(result->IsDoubleRegister()); | 4736 ASSERT(result->IsDoubleRegister()); |
| 4842 | 4737 |
| 4843 Register input_reg = ToRegister(input); | 4738 Register input_reg = ToRegister(input); |
| 4844 XMMRegister result_reg = ToDoubleRegister(result); | 4739 XMMRegister result_reg = ToDoubleRegister(result); |
| 4845 | 4740 |
| 4846 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED; | |
| 4847 HValue* value = instr->hydrogen()->value(); | 4741 HValue* value = instr->hydrogen()->value(); |
| 4848 if (value->type().IsSmi()) { | 4742 NumberUntagDMode mode = value->representation().IsSmi() |
| 4849 mode = NUMBER_CANDIDATE_IS_SMI; | 4743 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 4850 } else if (value->IsLoadKeyed()) { | |
| 4851 HLoadKeyed* load = HLoadKeyed::cast(value); | |
| 4852 if (load->UsesMustHandleHole()) { | |
| 4853 mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE; | |
| 4854 } | |
| 4855 } | |
| 4856 | 4744 |
| 4857 EmitNumberUntagD(input_reg, result_reg, | 4745 EmitNumberUntagD(input_reg, result_reg, |
| 4858 instr->hydrogen()->allow_undefined_as_nan(), | 4746 instr->hydrogen()->can_convert_undefined_to_nan(), |
| 4859 instr->hydrogen()->deoptimize_on_minus_zero(), | 4747 instr->hydrogen()->deoptimize_on_minus_zero(), |
| 4860 instr->environment(), | 4748 instr->environment(), |
| 4861 mode); | 4749 mode); |
| 4862 } | 4750 } |
| 4863 | 4751 |
| 4864 | 4752 |
| 4865 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4753 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 4866 LOperand* input = instr->value(); | 4754 LOperand* input = instr->value(); |
| 4867 ASSERT(input->IsDoubleRegister()); | 4755 ASSERT(input->IsDoubleRegister()); |
| 4868 LOperand* result = instr->result(); | 4756 LOperand* result = instr->result(); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5014 PushSafepointRegistersScope scope(this); | 4902 PushSafepointRegistersScope scope(this); |
| 5015 __ push(object); | 4903 __ push(object); |
| 5016 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 4904 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); |
| 5017 __ testq(rax, Immediate(kSmiTagMask)); | 4905 __ testq(rax, Immediate(kSmiTagMask)); |
| 5018 } | 4906 } |
| 5019 DeoptimizeIf(zero, instr->environment()); | 4907 DeoptimizeIf(zero, instr->environment()); |
| 5020 } | 4908 } |
| 5021 | 4909 |
| 5022 | 4910 |
| 5023 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4911 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5024 class DeferredCheckMaps: public LDeferredCode { | 4912 class DeferredCheckMaps V8_FINAL : public LDeferredCode { |
| 5025 public: | 4913 public: |
| 5026 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 4914 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| 5027 : LDeferredCode(codegen), instr_(instr), object_(object) { | 4915 : LDeferredCode(codegen), instr_(instr), object_(object) { |
| 5028 SetExit(check_maps()); | 4916 SetExit(check_maps()); |
| 5029 } | 4917 } |
| 5030 virtual void Generate() { | 4918 virtual void Generate() V8_OVERRIDE { |
| 5031 codegen()->DoDeferredInstanceMigration(instr_, object_); | 4919 codegen()->DoDeferredInstanceMigration(instr_, object_); |
| 5032 } | 4920 } |
| 5033 Label* check_maps() { return &check_maps_; } | 4921 Label* check_maps() { return &check_maps_; } |
| 5034 virtual LInstruction* instr() { return instr_; } | 4922 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5035 private: | 4923 private: |
| 5036 LCheckMaps* instr_; | 4924 LCheckMaps* instr_; |
| 5037 Label check_maps_; | 4925 Label check_maps_; |
| 5038 Register object_; | 4926 Register object_; |
| 5039 }; | 4927 }; |
| 5040 | 4928 |
| 5041 if (instr->hydrogen()->CanOmitMapChecks()) return; | 4929 if (instr->hydrogen()->CanOmitMapChecks()) return; |
| 5042 | 4930 |
| 5043 LOperand* input = instr->value(); | 4931 LOperand* input = instr->value(); |
| 5044 ASSERT(input->IsRegister()); | 4932 ASSERT(input->IsRegister()); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5114 // smi | 5002 // smi |
| 5115 __ bind(&is_smi); | 5003 __ bind(&is_smi); |
| 5116 __ SmiToInteger32(input_reg, input_reg); | 5004 __ SmiToInteger32(input_reg, input_reg); |
| 5117 __ ClampUint8(input_reg); | 5005 __ ClampUint8(input_reg); |
| 5118 | 5006 |
| 5119 __ bind(&done); | 5007 __ bind(&done); |
| 5120 } | 5008 } |
| 5121 | 5009 |
| 5122 | 5010 |
| 5123 void LCodeGen::DoAllocate(LAllocate* instr) { | 5011 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 5124 class DeferredAllocate: public LDeferredCode { | 5012 class DeferredAllocate V8_FINAL : public LDeferredCode { |
| 5125 public: | 5013 public: |
| 5126 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5014 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 5127 : LDeferredCode(codegen), instr_(instr) { } | 5015 : LDeferredCode(codegen), instr_(instr) { } |
| 5128 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5016 virtual void Generate() V8_OVERRIDE { |
| 5129 virtual LInstruction* instr() { return instr_; } | 5017 codegen()->DoDeferredAllocate(instr_); |
| 5018 } |
| 5019 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5130 private: | 5020 private: |
| 5131 LAllocate* instr_; | 5021 LAllocate* instr_; |
| 5132 }; | 5022 }; |
| 5133 | 5023 |
| 5134 DeferredAllocate* deferred = | 5024 DeferredAllocate* deferred = |
| 5135 new(zone()) DeferredAllocate(this, instr); | 5025 new(zone()) DeferredAllocate(this, instr); |
| 5136 | 5026 |
| 5137 Register result = ToRegister(instr->result()); | 5027 Register result = ToRegister(instr->result()); |
| 5138 Register temp = ToRegister(instr->temp()); | 5028 Register temp = ToRegister(instr->temp()); |
| 5139 | 5029 |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5452 | 5342 |
| 5453 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5343 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 5454 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5344 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5455 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5345 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| 5456 // needed return address), even though the implementation of LAZY and EAGER is | 5346 // needed return address), even though the implementation of LAZY and EAGER is |
| 5457 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5347 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 5458 // the special case below. | 5348 // the special case below. |
| 5459 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5349 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5460 type = Deoptimizer::LAZY; | 5350 type = Deoptimizer::LAZY; |
| 5461 } | 5351 } |
| 5352 |
| 5353 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5462 DeoptimizeIf(no_condition, instr->environment(), type); | 5354 DeoptimizeIf(no_condition, instr->environment(), type); |
| 5463 } | 5355 } |
| 5464 | 5356 |
| 5465 | 5357 |
| 5466 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5358 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5467 // Nothing to see here, move on! | 5359 // Nothing to see here, move on! |
| 5468 } | 5360 } |
| 5469 | 5361 |
| 5470 | 5362 |
| 5471 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5363 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 5472 PushSafepointRegistersScope scope(this); | 5364 PushSafepointRegistersScope scope(this); |
| 5473 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 5365 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 5474 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5366 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 5475 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); | 5367 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); |
| 5476 ASSERT(instr->HasEnvironment()); | 5368 ASSERT(instr->HasEnvironment()); |
| 5477 LEnvironment* env = instr->environment(); | 5369 LEnvironment* env = instr->environment(); |
| 5478 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5370 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5479 } | 5371 } |
| 5480 | 5372 |
| 5481 | 5373 |
| 5482 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5374 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| 5483 class DeferredStackCheck: public LDeferredCode { | 5375 class DeferredStackCheck V8_FINAL : public LDeferredCode { |
| 5484 public: | 5376 public: |
| 5485 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 5377 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
| 5486 : LDeferredCode(codegen), instr_(instr) { } | 5378 : LDeferredCode(codegen), instr_(instr) { } |
| 5487 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 5379 virtual void Generate() V8_OVERRIDE { |
| 5488 virtual LInstruction* instr() { return instr_; } | 5380 codegen()->DoDeferredStackCheck(instr_); |
| 5381 } |
| 5382 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5489 private: | 5383 private: |
| 5490 LStackCheck* instr_; | 5384 LStackCheck* instr_; |
| 5491 }; | 5385 }; |
| 5492 | 5386 |
| 5493 ASSERT(instr->HasEnvironment()); | 5387 ASSERT(instr->HasEnvironment()); |
| 5494 LEnvironment* env = instr->environment(); | 5388 LEnvironment* env = instr->environment(); |
| 5495 // There is no LLazyBailout instruction for stack-checks. We have to | 5389 // There is no LLazyBailout instruction for stack-checks. We have to |
| 5496 // prepare for lazy deoptimization explicitly here. | 5390 // prepare for lazy deoptimization explicitly here. |
| 5497 if (instr->hydrogen()->is_function_entry()) { | 5391 if (instr->hydrogen()->is_function_entry()) { |
| 5498 // Perform stack overflow check. | 5392 // Perform stack overflow check. |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5629 FixedArray::kHeaderSize - kPointerSize)); | 5523 FixedArray::kHeaderSize - kPointerSize)); |
| 5630 __ bind(&done); | 5524 __ bind(&done); |
| 5631 } | 5525 } |
| 5632 | 5526 |
| 5633 | 5527 |
| 5634 #undef __ | 5528 #undef __ |
| 5635 | 5529 |
| 5636 } } // namespace v8::internal | 5530 } } // namespace v8::internal |
| 5637 | 5531 |
| 5638 #endif // V8_TARGET_ARCH_X64 | 5532 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |