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 2119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2130 __ Ldr(map_reg, FieldMemOperand(object, HeapObject::kMapOffset)); | 2130 __ Ldr(map_reg, FieldMemOperand(object, HeapObject::kMapOffset)); |
2131 | 2131 |
2132 DeferredCheckMaps* deferred = NULL; | 2132 DeferredCheckMaps* deferred = NULL; |
2133 if (instr->hydrogen()->has_migration_target()) { | 2133 if (instr->hydrogen()->has_migration_target()) { |
2134 deferred = new(zone()) DeferredCheckMaps(this, instr, object); | 2134 deferred = new(zone()) DeferredCheckMaps(this, instr, object); |
2135 __ Bind(deferred->check_maps()); | 2135 __ Bind(deferred->check_maps()); |
2136 } | 2136 } |
2137 | 2137 |
2138 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); | 2138 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); |
2139 Label success; | 2139 Label success; |
2140 for (int i = 0; i < map_set.size(); i++) { | 2140 for (int i = 0; i < map_set.size() - 1; i++) { |
2141 Handle<Map> map = map_set.at(i).handle(); | 2141 Handle<Map> map = map_set.at(i).handle(); |
2142 __ CompareMap(map_reg, map); | 2142 __ CompareMap(map_reg, map); |
2143 __ B(eq, &success); | 2143 __ B(eq, &success); |
2144 } | 2144 } |
| 2145 Handle<Map> map = map_set.at(map_set.size() - 1).handle(); |
| 2146 __ CompareMap(map_reg, map); |
2145 | 2147 |
2146 // We didn't match a map. | 2148 // We didn't match a map. |
2147 if (instr->hydrogen()->has_migration_target()) { | 2149 if (instr->hydrogen()->has_migration_target()) { |
2148 __ B(deferred->entry()); | 2150 __ B(ne, deferred->entry()); |
2149 } else { | 2151 } else { |
2150 Deoptimize(instr->environment()); | 2152 DeoptimizeIf(ne, instr->environment()); |
2151 } | 2153 } |
2152 | 2154 |
2153 __ Bind(&success); | 2155 __ Bind(&success); |
2154 } | 2156 } |
2155 | 2157 |
2156 | 2158 |
2157 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 2159 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
2158 if (!instr->hydrogen()->value()->IsHeapObject()) { | 2160 if (!instr->hydrogen()->value()->IsHeapObject()) { |
2159 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment()); | 2161 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment()); |
2160 } | 2162 } |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2574 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2576 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
2575 } | 2577 } |
2576 | 2578 |
2577 | 2579 |
2578 void LCodeGen::DoDateField(LDateField* instr) { | 2580 void LCodeGen::DoDateField(LDateField* instr) { |
2579 Register object = ToRegister(instr->date()); | 2581 Register object = ToRegister(instr->date()); |
2580 Register result = ToRegister(instr->result()); | 2582 Register result = ToRegister(instr->result()); |
2581 Register temp1 = x10; | 2583 Register temp1 = x10; |
2582 Register temp2 = x11; | 2584 Register temp2 = x11; |
2583 Smi* index = instr->index(); | 2585 Smi* index = instr->index(); |
2584 Label runtime, done, deopt, obj_ok; | 2586 Label runtime, done; |
2585 | 2587 |
2586 ASSERT(object.is(result) && object.Is(x0)); | 2588 ASSERT(object.is(result) && object.Is(x0)); |
2587 ASSERT(instr->IsMarkedAsCall()); | 2589 ASSERT(instr->IsMarkedAsCall()); |
2588 | 2590 |
2589 __ JumpIfSmi(object, &deopt); | 2591 DeoptimizeIfSmi(object, instr->environment()); |
2590 __ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE); | 2592 __ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE); |
2591 __ B(eq, &obj_ok); | 2593 DeoptimizeIf(ne, instr->environment()); |
2592 | 2594 |
2593 __ Bind(&deopt); | |
2594 Deoptimize(instr->environment()); | |
2595 | |
2596 __ Bind(&obj_ok); | |
2597 if (index->value() == 0) { | 2595 if (index->value() == 0) { |
2598 __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); | 2596 __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); |
2599 } else { | 2597 } else { |
2600 if (index->value() < JSDate::kFirstUncachedField) { | 2598 if (index->value() < JSDate::kFirstUncachedField) { |
2601 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 2599 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
2602 __ Mov(temp1, Operand(stamp)); | 2600 __ Mov(temp1, Operand(stamp)); |
2603 __ Ldr(temp1, MemOperand(temp1)); | 2601 __ Ldr(temp1, MemOperand(temp1)); |
2604 __ Ldr(temp2, FieldMemOperand(object, JSDate::kCacheStampOffset)); | 2602 __ Ldr(temp2, FieldMemOperand(object, JSDate::kCacheStampOffset)); |
2605 __ Cmp(temp1, temp2); | 2603 __ Cmp(temp1, temp2); |
2606 __ B(ne, &runtime); | 2604 __ B(ne, &runtime); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2717 | 2715 |
2718 // Issue the division first, and then check for any deopt cases whilst the | 2716 // Issue the division first, and then check for any deopt cases whilst the |
2719 // result is computed. | 2717 // result is computed. |
2720 __ Sdiv(result, dividend, divisor); | 2718 __ Sdiv(result, dividend, divisor); |
2721 | 2719 |
2722 if (hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 2720 if (hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
2723 ASSERT_EQ(NULL, instr->temp()); | 2721 ASSERT_EQ(NULL, instr->temp()); |
2724 return; | 2722 return; |
2725 } | 2723 } |
2726 | 2724 |
2727 Label deopt; | |
2728 // Check for x / 0. | 2725 // Check for x / 0. |
2729 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 2726 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
2730 __ Cbz(divisor, &deopt); | 2727 DeoptimizeIfZero(divisor, instr->environment()); |
2731 } | 2728 } |
2732 | 2729 |
2733 // Check for (0 / -x) as that will produce negative zero. | 2730 // Check for (0 / -x) as that will produce negative zero. |
2734 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2731 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
2735 __ Cmp(divisor, 0); | 2732 __ Cmp(divisor, 0); |
2736 | 2733 |
2737 // If the divisor < 0 (mi), compare the dividend, and deopt if it is | 2734 // If the divisor < 0 (mi), compare the dividend, and deopt if it is |
2738 // zero, ie. zero dividend with negative divisor deopts. | 2735 // zero, ie. zero dividend with negative divisor deopts. |
2739 // If the divisor >= 0 (pl, the opposite of mi) set the flags to | 2736 // If the divisor >= 0 (pl, the opposite of mi) set the flags to |
2740 // condition ne, so we don't deopt, ie. positive divisor doesn't deopt. | 2737 // condition ne, so we don't deopt, ie. positive divisor doesn't deopt. |
2741 __ Ccmp(dividend, 0, NoFlag, mi); | 2738 __ Ccmp(dividend, 0, NoFlag, mi); |
2742 __ B(eq, &deopt); | 2739 DeoptimizeIf(eq, instr->environment()); |
2743 } | 2740 } |
2744 | 2741 |
2745 // Check for (kMinInt / -1). | 2742 // Check for (kMinInt / -1). |
2746 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 2743 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
2747 // Test dividend for kMinInt by subtracting one (cmp) and checking for | 2744 // Test dividend for kMinInt by subtracting one (cmp) and checking for |
2748 // overflow. | 2745 // overflow. |
2749 __ Cmp(dividend, 1); | 2746 __ Cmp(dividend, 1); |
2750 // If overflow is set, ie. dividend = kMinInt, compare the divisor with | 2747 // If overflow is set, ie. dividend = kMinInt, compare the divisor with |
2751 // -1. If overflow is clear, set the flags for condition ne, as the | 2748 // -1. If overflow is clear, set the flags for condition ne, as the |
2752 // dividend isn't -1, and thus we shouldn't deopt. | 2749 // dividend isn't -1, and thus we shouldn't deopt. |
2753 __ Ccmp(divisor, -1, NoFlag, vs); | 2750 __ Ccmp(divisor, -1, NoFlag, vs); |
2754 __ B(eq, &deopt); | 2751 DeoptimizeIf(eq, instr->environment()); |
2755 } | 2752 } |
2756 | 2753 |
2757 // Compute remainder and deopt if it's not zero. | 2754 // Compute remainder and deopt if it's not zero. |
2758 Register remainder = ToRegister32(instr->temp()); | 2755 Register remainder = ToRegister32(instr->temp()); |
2759 __ Msub(remainder, result, divisor, dividend); | 2756 __ Msub(remainder, result, divisor, dividend); |
2760 __ Cbnz(remainder, &deopt); | 2757 DeoptimizeIfNotZero(remainder, instr->environment()); |
2761 | |
2762 Label div_ok; | |
2763 __ B(&div_ok); | |
2764 __ Bind(&deopt); | |
2765 Deoptimize(instr->environment()); | |
2766 __ Bind(&div_ok); | |
2767 } | 2758 } |
2768 | 2759 |
2769 | 2760 |
2770 void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) { | 2761 void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) { |
2771 DoubleRegister input = ToDoubleRegister(instr->value()); | 2762 DoubleRegister input = ToDoubleRegister(instr->value()); |
2772 Register result = ToRegister32(instr->result()); | 2763 Register result = ToRegister32(instr->result()); |
2773 | 2764 |
2774 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2765 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
2775 DeoptimizeIfMinusZero(input, instr->environment()); | 2766 DeoptimizeIfMinusZero(input, instr->environment()); |
2776 } | 2767 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2843 } | 2834 } |
2844 | 2835 |
2845 | 2836 |
2846 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 2837 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
2847 Register object = ToRegister(instr->object()); | 2838 Register object = ToRegister(instr->object()); |
2848 Register null_value = x5; | 2839 Register null_value = x5; |
2849 | 2840 |
2850 ASSERT(instr->IsMarkedAsCall()); | 2841 ASSERT(instr->IsMarkedAsCall()); |
2851 ASSERT(object.Is(x0)); | 2842 ASSERT(object.Is(x0)); |
2852 | 2843 |
2853 Label deopt; | 2844 DeoptimizeIfRoot(object, Heap::kUndefinedValueRootIndex, |
2854 | 2845 instr->environment()); |
2855 __ JumpIfRoot(object, Heap::kUndefinedValueRootIndex, &deopt); | |
2856 | 2846 |
2857 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 2847 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
2858 __ Cmp(object, null_value); | 2848 __ Cmp(object, null_value); |
2859 __ B(eq, &deopt); | 2849 DeoptimizeIf(eq, instr->environment()); |
2860 | 2850 |
2861 __ JumpIfSmi(object, &deopt); | 2851 DeoptimizeIfSmi(object, instr->environment()); |
2862 | 2852 |
2863 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 2853 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
2864 __ CompareObjectType(object, x1, x1, LAST_JS_PROXY_TYPE); | 2854 __ CompareObjectType(object, x1, x1, LAST_JS_PROXY_TYPE); |
2865 __ B(le, &deopt); | 2855 DeoptimizeIf(le, instr->environment()); |
2866 | 2856 |
2867 Label use_cache, call_runtime; | 2857 Label use_cache, call_runtime; |
2868 __ CheckEnumCache(object, null_value, x1, x2, x3, x4, &call_runtime); | 2858 __ CheckEnumCache(object, null_value, x1, x2, x3, x4, &call_runtime); |
2869 | 2859 |
2870 __ Ldr(object, FieldMemOperand(object, HeapObject::kMapOffset)); | 2860 __ Ldr(object, FieldMemOperand(object, HeapObject::kMapOffset)); |
2871 __ B(&use_cache); | 2861 __ B(&use_cache); |
2872 | 2862 |
2873 __ Bind(&deopt); | |
2874 Deoptimize(instr->environment()); | |
2875 | |
2876 // Get the set of properties to enumerate. | 2863 // Get the set of properties to enumerate. |
2877 __ Bind(&call_runtime); | 2864 __ Bind(&call_runtime); |
2878 __ Push(object); | 2865 __ Push(object); |
2879 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 2866 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
2880 | 2867 |
2881 __ Ldr(x1, FieldMemOperand(object, HeapObject::kMapOffset)); | 2868 __ Ldr(x1, FieldMemOperand(object, HeapObject::kMapOffset)); |
2882 __ JumpIfNotRoot(x1, Heap::kMetaMapRootIndex, &deopt); | 2869 DeoptimizeIfNotRoot(x1, Heap::kMetaMapRootIndex, instr->environment()); |
2883 | 2870 |
2884 __ Bind(&use_cache); | 2871 __ Bind(&use_cache); |
2885 } | 2872 } |
2886 | 2873 |
2887 | 2874 |
2888 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2875 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2889 Register input = ToRegister(instr->value()); | 2876 Register input = ToRegister(instr->value()); |
2890 Register result = ToRegister(instr->result()); | 2877 Register result = ToRegister(instr->result()); |
2891 | 2878 |
2892 __ AssertString(input); | 2879 __ AssertString(input); |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3280 __ Bind(¬_the_hole); | 3267 __ Bind(¬_the_hole); |
3281 } | 3268 } |
3282 } | 3269 } |
3283 } | 3270 } |
3284 | 3271 |
3285 | 3272 |
3286 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 3273 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
3287 Register function = ToRegister(instr->function()); | 3274 Register function = ToRegister(instr->function()); |
3288 Register result = ToRegister(instr->result()); | 3275 Register result = ToRegister(instr->result()); |
3289 Register temp = ToRegister(instr->temp()); | 3276 Register temp = ToRegister(instr->temp()); |
3290 Label deopt; | |
3291 | 3277 |
3292 // Check that the function really is a function. Leaves map in the result | 3278 // Check that the function really is a function. Leaves map in the result |
3293 // register. | 3279 // register. |
3294 __ JumpIfNotObjectType(function, result, temp, JS_FUNCTION_TYPE, &deopt); | 3280 __ CompareObjectType(function, result, temp, JS_FUNCTION_TYPE); |
| 3281 DeoptimizeIf(ne, instr->environment()); |
3295 | 3282 |
3296 // Make sure that the function has an instance prototype. | 3283 // Make sure that the function has an instance prototype. |
3297 Label non_instance; | 3284 Label non_instance; |
3298 __ Ldrb(temp, FieldMemOperand(result, Map::kBitFieldOffset)); | 3285 __ Ldrb(temp, FieldMemOperand(result, Map::kBitFieldOffset)); |
3299 __ Tbnz(temp, Map::kHasNonInstancePrototype, &non_instance); | 3286 __ Tbnz(temp, Map::kHasNonInstancePrototype, &non_instance); |
3300 | 3287 |
3301 // Get the prototype or initial map from the function. | 3288 // Get the prototype or initial map from the function. |
3302 __ Ldr(result, FieldMemOperand(function, | 3289 __ Ldr(result, FieldMemOperand(function, |
3303 JSFunction::kPrototypeOrInitialMapOffset)); | 3290 JSFunction::kPrototypeOrInitialMapOffset)); |
3304 | 3291 |
3305 // Check that the function has a prototype or an initial map. | 3292 // Check that the function has a prototype or an initial map. |
3306 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &deopt); | 3293 DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, |
| 3294 instr->environment()); |
3307 | 3295 |
3308 // If the function does not have an initial map, we're done. | 3296 // If the function does not have an initial map, we're done. |
3309 Label done; | 3297 Label done; |
3310 __ CompareObjectType(result, temp, temp, MAP_TYPE); | 3298 __ CompareObjectType(result, temp, temp, MAP_TYPE); |
3311 __ B(ne, &done); | 3299 __ B(ne, &done); |
3312 | 3300 |
3313 // Get the prototype from the initial map. | 3301 // Get the prototype from the initial map. |
3314 __ Ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 3302 __ Ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
3315 __ B(&done); | 3303 __ B(&done); |
3316 | 3304 |
3317 // Non-instance prototype: fetch prototype from constructor field in initial | 3305 // Non-instance prototype: fetch prototype from constructor field in initial |
3318 // map. | 3306 // map. |
3319 __ Bind(&non_instance); | 3307 __ Bind(&non_instance); |
3320 __ Ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); | 3308 __ Ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
3321 __ B(&done); | |
3322 | |
3323 // Deoptimize case. | |
3324 __ Bind(&deopt); | |
3325 Deoptimize(instr->environment()); | |
3326 | 3309 |
3327 // All done. | 3310 // All done. |
3328 __ Bind(&done); | 3311 __ Bind(&done); |
3329 } | 3312 } |
3330 | 3313 |
3331 | 3314 |
3332 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 3315 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
3333 Register result = ToRegister(instr->result()); | 3316 Register result = ToRegister(instr->result()); |
3334 __ Mov(result, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); | 3317 __ Mov(result, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); |
3335 __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); | 3318 __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3683 Representation r = instr->hydrogen()->value()->representation(); | 3666 Representation r = instr->hydrogen()->value()->representation(); |
3684 if (r.IsDouble()) { | 3667 if (r.IsDouble()) { |
3685 DoubleRegister input = ToDoubleRegister(instr->value()); | 3668 DoubleRegister input = ToDoubleRegister(instr->value()); |
3686 DoubleRegister result = ToDoubleRegister(instr->result()); | 3669 DoubleRegister result = ToDoubleRegister(instr->result()); |
3687 __ Fabs(result, input); | 3670 __ Fabs(result, input); |
3688 } else if (r.IsSmi() || r.IsInteger32()) { | 3671 } else if (r.IsSmi() || r.IsInteger32()) { |
3689 Register input = r.IsSmi() ? ToRegister(instr->value()) | 3672 Register input = r.IsSmi() ? ToRegister(instr->value()) |
3690 : ToRegister32(instr->value()); | 3673 : ToRegister32(instr->value()); |
3691 Register result = r.IsSmi() ? ToRegister(instr->result()) | 3674 Register result = r.IsSmi() ? ToRegister(instr->result()) |
3692 : ToRegister32(instr->result()); | 3675 : ToRegister32(instr->result()); |
3693 Label done; | 3676 __ Abs(result, input); |
3694 __ Abs(result, input, NULL, &done); | 3677 DeoptimizeIf(vs, instr->environment()); |
3695 Deoptimize(instr->environment()); | |
3696 __ Bind(&done); | |
3697 } | 3678 } |
3698 } | 3679 } |
3699 | 3680 |
3700 | 3681 |
3701 void LCodeGen::DoDeferredMathAbsTagged(LMathAbsTagged* instr, | 3682 void LCodeGen::DoDeferredMathAbsTagged(LMathAbsTagged* instr, |
3702 Label* exit, | 3683 Label* exit, |
3703 Label* allocation_entry) { | 3684 Label* allocation_entry) { |
3704 // Handle the tricky cases of MathAbsTagged: | 3685 // Handle the tricky cases of MathAbsTagged: |
3705 // - HeapNumber inputs. | 3686 // - HeapNumber inputs. |
3706 // - Negative inputs produce a positive result, so a new HeapNumber is | 3687 // - Negative inputs produce a positive result, so a new HeapNumber is |
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4217 __ bind(&remainder_not_zero); | 4198 __ bind(&remainder_not_zero); |
4218 } | 4199 } |
4219 } | 4200 } |
4220 | 4201 |
4221 | 4202 |
4222 void LCodeGen::DoModI(LModI* instr) { | 4203 void LCodeGen::DoModI(LModI* instr) { |
4223 Register dividend = ToRegister32(instr->left()); | 4204 Register dividend = ToRegister32(instr->left()); |
4224 Register divisor = ToRegister32(instr->right()); | 4205 Register divisor = ToRegister32(instr->right()); |
4225 Register result = ToRegister32(instr->result()); | 4206 Register result = ToRegister32(instr->result()); |
4226 | 4207 |
4227 Label deopt, done; | 4208 Label done; |
4228 // modulo = dividend - quotient * divisor | 4209 // modulo = dividend - quotient * divisor |
4229 __ Sdiv(result, dividend, divisor); | 4210 __ Sdiv(result, dividend, divisor); |
4230 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 4211 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
4231 // Combine the deoptimization sites. | 4212 DeoptimizeIfZero(divisor, instr->environment()); |
4232 Label ok; | |
4233 __ Cbnz(divisor, &ok); | |
4234 __ Bind(&deopt); | |
4235 Deoptimize(instr->environment()); | |
4236 __ Bind(&ok); | |
4237 } | 4213 } |
4238 __ Msub(result, result, divisor, dividend); | 4214 __ Msub(result, result, divisor, dividend); |
4239 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4215 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4240 __ Cbnz(result, &done); | 4216 __ Cbnz(result, &done); |
4241 if (deopt.is_bound()) { // TODO(all) This is a hack, remove this... | 4217 DeoptimizeIfNegative(dividend, instr->environment()); |
4242 __ Tbnz(dividend, kWSignBit, &deopt); | |
4243 } else { | |
4244 DeoptimizeIfNegative(dividend, instr->environment()); | |
4245 } | |
4246 } | 4218 } |
4247 __ Bind(&done); | 4219 __ Bind(&done); |
4248 } | 4220 } |
4249 | 4221 |
4250 | 4222 |
4251 void LCodeGen::DoMulConstIS(LMulConstIS* instr) { | 4223 void LCodeGen::DoMulConstIS(LMulConstIS* instr) { |
4252 ASSERT(instr->hydrogen()->representation().IsSmiOrInteger32()); | 4224 ASSERT(instr->hydrogen()->representation().IsSmiOrInteger32()); |
4253 bool is_smi = instr->hydrogen()->representation().IsSmi(); | 4225 bool is_smi = instr->hydrogen()->representation().IsSmi(); |
4254 Register result = | 4226 Register result = |
4255 is_smi ? ToRegister(instr->result()) : ToRegister32(instr->result()); | 4227 is_smi ? ToRegister(instr->result()) : ToRegister32(instr->result()); |
(...skipping 1445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5701 __ Bind(¬_applicable); | 5673 __ Bind(¬_applicable); |
5702 } | 5674 } |
5703 | 5675 |
5704 | 5676 |
5705 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 5677 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
5706 Register object = ToRegister(instr->object()); | 5678 Register object = ToRegister(instr->object()); |
5707 Register temp1 = ToRegister(instr->temp1()); | 5679 Register temp1 = ToRegister(instr->temp1()); |
5708 Register temp2 = ToRegister(instr->temp2()); | 5680 Register temp2 = ToRegister(instr->temp2()); |
5709 | 5681 |
5710 Label no_memento_found; | 5682 Label no_memento_found; |
5711 __ JumpIfJSArrayHasAllocationMemento(object, temp1, temp2, &no_memento_found); | 5683 __ TestJSArrayForAllocationMemento(object, temp1, temp2, &no_memento_found); |
5712 Deoptimize(instr->environment()); | 5684 DeoptimizeIf(eq, instr->environment()); |
5713 __ Bind(&no_memento_found); | 5685 __ Bind(&no_memento_found); |
5714 } | 5686 } |
5715 | 5687 |
5716 | 5688 |
5717 void LCodeGen::DoTruncateDoubleToIntOrSmi(LTruncateDoubleToIntOrSmi* instr) { | 5689 void LCodeGen::DoTruncateDoubleToIntOrSmi(LTruncateDoubleToIntOrSmi* instr) { |
5718 DoubleRegister input = ToDoubleRegister(instr->value()); | 5690 DoubleRegister input = ToDoubleRegister(instr->value()); |
5719 Register result = ToRegister(instr->result()); | 5691 Register result = ToRegister(instr->result()); |
5720 __ TruncateDoubleToI(result, input); | 5692 __ TruncateDoubleToI(result, input); |
5721 if (instr->tag_result()) { | 5693 if (instr->tag_result()) { |
5722 __ SmiTag(result, result); | 5694 __ SmiTag(result, result); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5835 | 5807 |
5836 | 5808 |
5837 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 5809 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
5838 Register receiver = ToRegister(instr->receiver()); | 5810 Register receiver = ToRegister(instr->receiver()); |
5839 Register function = ToRegister(instr->function()); | 5811 Register function = ToRegister(instr->function()); |
5840 Register result = ToRegister(instr->result()); | 5812 Register result = ToRegister(instr->result()); |
5841 | 5813 |
5842 // If the receiver is null or undefined, we have to pass the global object as | 5814 // If the receiver is null or undefined, we have to pass the global object as |
5843 // a receiver to normal functions. Values have to be passed unchanged to | 5815 // a receiver to normal functions. Values have to be passed unchanged to |
5844 // builtins and strict-mode functions. | 5816 // builtins and strict-mode functions. |
5845 Label global_object, done, deopt; | 5817 Label global_object, done; |
5846 | 5818 |
5847 if (!instr->hydrogen()->known_function()) { | 5819 if (!instr->hydrogen()->known_function()) { |
5848 __ Ldr(result, FieldMemOperand(function, | 5820 __ Ldr(result, FieldMemOperand(function, |
5849 JSFunction::kSharedFunctionInfoOffset)); | 5821 JSFunction::kSharedFunctionInfoOffset)); |
5850 | 5822 |
5851 // CompilerHints is an int32 field. See objects.h. | 5823 // CompilerHints is an int32 field. See objects.h. |
5852 __ Ldr(result.W(), | 5824 __ Ldr(result.W(), |
5853 FieldMemOperand(result, SharedFunctionInfo::kCompilerHintsOffset)); | 5825 FieldMemOperand(result, SharedFunctionInfo::kCompilerHintsOffset)); |
5854 | 5826 |
5855 // Do not transform the receiver to object for strict mode functions. | 5827 // Do not transform the receiver to object for strict mode functions. |
5856 __ Tbnz(result, SharedFunctionInfo::kStrictModeFunction, &done); | 5828 __ Tbnz(result, SharedFunctionInfo::kStrictModeFunction, &done); |
5857 | 5829 |
5858 // Do not transform the receiver to object for builtins. | 5830 // Do not transform the receiver to object for builtins. |
5859 __ Tbnz(result, SharedFunctionInfo::kNative, &done); | 5831 __ Tbnz(result, SharedFunctionInfo::kNative, &done); |
5860 } | 5832 } |
5861 | 5833 |
5862 // Normal function. Replace undefined or null with global receiver. | 5834 // Normal function. Replace undefined or null with global receiver. |
5863 __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &global_object); | 5835 __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &global_object); |
5864 __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, &global_object); | 5836 __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, &global_object); |
5865 | 5837 |
5866 // Deoptimize if the receiver is not a JS object. | 5838 // Deoptimize if the receiver is not a JS object. |
5867 __ JumpIfSmi(receiver, &deopt); | 5839 DeoptimizeIfSmi(receiver, instr->environment()); |
5868 __ CompareObjectType(receiver, result, result, FIRST_SPEC_OBJECT_TYPE); | 5840 __ CompareObjectType(receiver, result, result, FIRST_SPEC_OBJECT_TYPE); |
5869 __ Mov(result, receiver); | 5841 __ Mov(result, receiver); |
5870 __ B(ge, &done); | 5842 __ B(ge, &done); |
5871 // Otherwise, fall through to deopt. | |
5872 | |
5873 __ Bind(&deopt); | |
5874 Deoptimize(instr->environment()); | 5843 Deoptimize(instr->environment()); |
5875 | 5844 |
5876 __ Bind(&global_object); | 5845 __ Bind(&global_object); |
5877 __ Ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 5846 __ Ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
5878 __ Ldr(result, ContextMemOperand(result, Context::GLOBAL_OBJECT_INDEX)); | 5847 __ Ldr(result, ContextMemOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
5879 __ Ldr(result, FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset)); | 5848 __ Ldr(result, FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset)); |
5880 | 5849 |
5881 __ Bind(&done); | 5850 __ Bind(&done); |
5882 } | 5851 } |
5883 | 5852 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5950 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5919 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
5951 // Index is equal to negated out of object property index plus 1. | 5920 // Index is equal to negated out of object property index plus 1. |
5952 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5921 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
5953 __ Ldr(result, FieldMemOperand(result, | 5922 __ Ldr(result, FieldMemOperand(result, |
5954 FixedArray::kHeaderSize - kPointerSize)); | 5923 FixedArray::kHeaderSize - kPointerSize)); |
5955 __ Bind(deferred->exit()); | 5924 __ Bind(deferred->exit()); |
5956 __ Bind(&done); | 5925 __ Bind(&done); |
5957 } | 5926 } |
5958 | 5927 |
5959 } } // namespace v8::internal | 5928 } } // namespace v8::internal |
OLD | NEW |