| 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 |