Chromium Code Reviews| 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 |