Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Side by Side Diff: src/arm64/lithium-codegen-arm64.cc

Issue 225703002: ARM64: Use direct deoptimization exits. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/arm64/macro-assembler-arm64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
3280 __ Bind(&not_the_hole); 3275 __ Bind(&not_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
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
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
5701 __ Bind(&not_applicable); 5681 __ Bind(&not_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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/arm64/macro-assembler-arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698