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