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

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: fix map check 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 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
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
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
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
3280 __ Bind(&not_the_hole); 3267 __ Bind(&not_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
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
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
5701 __ Bind(&not_applicable); 5673 __ Bind(&not_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
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
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
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