ARM64: Use direct deoptimization exits.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/225703002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20515 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1f9f8fe9
...@@ -2137,17 +2137,19 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { ...@@ -2137,17 +2137,19 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
UniqueSet<Map> map_set = instr->hydrogen()->map_set(); UniqueSet<Map> map_set = instr->hydrogen()->map_set();
Label success; Label success;
for (int i = 0; i < map_set.size(); i++) { for (int i = 0; i < map_set.size() - 1; i++) {
Handle<Map> map = map_set.at(i).handle(); Handle<Map> map = map_set.at(i).handle();
__ CompareMap(map_reg, map); __ CompareMap(map_reg, map);
__ B(eq, &success); __ B(eq, &success);
} }
Handle<Map> map = map_set.at(map_set.size() - 1).handle();
__ CompareMap(map_reg, map);
// We didn't match a map. // We didn't match a map.
if (instr->hydrogen()->has_migration_target()) { if (instr->hydrogen()->has_migration_target()) {
__ B(deferred->entry()); __ B(ne, deferred->entry());
} else { } else {
Deoptimize(instr->environment()); DeoptimizeIf(ne, instr->environment());
} }
__ Bind(&success); __ Bind(&success);
...@@ -2581,19 +2583,15 @@ void LCodeGen::DoDateField(LDateField* instr) { ...@@ -2581,19 +2583,15 @@ void LCodeGen::DoDateField(LDateField* instr) {
Register temp1 = x10; Register temp1 = x10;
Register temp2 = x11; Register temp2 = x11;
Smi* index = instr->index(); Smi* index = instr->index();
Label runtime, done, deopt, obj_ok; Label runtime, done;
ASSERT(object.is(result) && object.Is(x0)); ASSERT(object.is(result) && object.Is(x0));
ASSERT(instr->IsMarkedAsCall()); ASSERT(instr->IsMarkedAsCall());
__ JumpIfSmi(object, &deopt); DeoptimizeIfSmi(object, instr->environment());
__ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE); __ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE);
__ B(eq, &obj_ok); DeoptimizeIf(ne, instr->environment());
__ Bind(&deopt);
Deoptimize(instr->environment());
__ Bind(&obj_ok);
if (index->value() == 0) { if (index->value() == 0) {
__ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
} else { } else {
...@@ -2724,10 +2722,9 @@ void LCodeGen::DoDivI(LDivI* instr) { ...@@ -2724,10 +2722,9 @@ void LCodeGen::DoDivI(LDivI* instr) {
return; return;
} }
Label deopt;
// Check for x / 0. // Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ Cbz(divisor, &deopt); DeoptimizeIfZero(divisor, instr->environment());
} }
// Check for (0 / -x) as that will produce negative zero. // Check for (0 / -x) as that will produce negative zero.
...@@ -2739,7 +2736,7 @@ void LCodeGen::DoDivI(LDivI* instr) { ...@@ -2739,7 +2736,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// If the divisor >= 0 (pl, the opposite of mi) set the flags to // If the divisor >= 0 (pl, the opposite of mi) set the flags to
// condition ne, so we don't deopt, ie. positive divisor doesn't deopt. // condition ne, so we don't deopt, ie. positive divisor doesn't deopt.
__ Ccmp(dividend, 0, NoFlag, mi); __ Ccmp(dividend, 0, NoFlag, mi);
__ B(eq, &deopt); DeoptimizeIf(eq, instr->environment());
} }
// Check for (kMinInt / -1). // Check for (kMinInt / -1).
...@@ -2751,19 +2748,13 @@ void LCodeGen::DoDivI(LDivI* instr) { ...@@ -2751,19 +2748,13 @@ void LCodeGen::DoDivI(LDivI* instr) {
// -1. If overflow is clear, set the flags for condition ne, as the // -1. If overflow is clear, set the flags for condition ne, as the
// dividend isn't -1, and thus we shouldn't deopt. // dividend isn't -1, and thus we shouldn't deopt.
__ Ccmp(divisor, -1, NoFlag, vs); __ Ccmp(divisor, -1, NoFlag, vs);
__ B(eq, &deopt); DeoptimizeIf(eq, instr->environment());
} }
// Compute remainder and deopt if it's not zero. // Compute remainder and deopt if it's not zero.
Register remainder = ToRegister32(instr->temp()); Register remainder = ToRegister32(instr->temp());
__ Msub(remainder, result, divisor, dividend); __ Msub(remainder, result, divisor, dividend);
__ Cbnz(remainder, &deopt); DeoptimizeIfNotZero(remainder, instr->environment());
Label div_ok;
__ B(&div_ok);
__ Bind(&deopt);
Deoptimize(instr->environment());
__ Bind(&div_ok);
} }
...@@ -2850,19 +2841,18 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { ...@@ -2850,19 +2841,18 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
ASSERT(instr->IsMarkedAsCall()); ASSERT(instr->IsMarkedAsCall());
ASSERT(object.Is(x0)); ASSERT(object.Is(x0));
Label deopt; DeoptimizeIfRoot(object, Heap::kUndefinedValueRootIndex,
instr->environment());
__ JumpIfRoot(object, Heap::kUndefinedValueRootIndex, &deopt);
__ LoadRoot(null_value, Heap::kNullValueRootIndex); __ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ Cmp(object, null_value); __ Cmp(object, null_value);
__ B(eq, &deopt); DeoptimizeIf(eq, instr->environment());
__ JumpIfSmi(object, &deopt); DeoptimizeIfSmi(object, instr->environment());
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ CompareObjectType(object, x1, x1, LAST_JS_PROXY_TYPE); __ CompareObjectType(object, x1, x1, LAST_JS_PROXY_TYPE);
__ B(le, &deopt); DeoptimizeIf(le, instr->environment());
Label use_cache, call_runtime; Label use_cache, call_runtime;
__ CheckEnumCache(object, null_value, x1, x2, x3, x4, &call_runtime); __ CheckEnumCache(object, null_value, x1, x2, x3, x4, &call_runtime);
...@@ -2870,16 +2860,13 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { ...@@ -2870,16 +2860,13 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ Ldr(object, FieldMemOperand(object, HeapObject::kMapOffset)); __ Ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
__ B(&use_cache); __ B(&use_cache);
__ Bind(&deopt);
Deoptimize(instr->environment());
// Get the set of properties to enumerate. // Get the set of properties to enumerate.
__ Bind(&call_runtime); __ Bind(&call_runtime);
__ Push(object); __ Push(object);
CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
__ Ldr(x1, FieldMemOperand(object, HeapObject::kMapOffset)); __ Ldr(x1, FieldMemOperand(object, HeapObject::kMapOffset));
__ JumpIfNotRoot(x1, Heap::kMetaMapRootIndex, &deopt); DeoptimizeIfNotRoot(x1, Heap::kMetaMapRootIndex, instr->environment());
__ Bind(&use_cache); __ Bind(&use_cache);
} }
...@@ -3287,11 +3274,11 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { ...@@ -3287,11 +3274,11 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
Register function = ToRegister(instr->function()); Register function = ToRegister(instr->function());
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
Register temp = ToRegister(instr->temp()); Register temp = ToRegister(instr->temp());
Label deopt;
// Check that the function really is a function. Leaves map in the result // Check that the function really is a function. Leaves map in the result
// register. // register.
__ JumpIfNotObjectType(function, result, temp, JS_FUNCTION_TYPE, &deopt); __ CompareObjectType(function, result, temp, JS_FUNCTION_TYPE);
DeoptimizeIf(ne, instr->environment());
// Make sure that the function has an instance prototype. // Make sure that the function has an instance prototype.
Label non_instance; Label non_instance;
...@@ -3303,7 +3290,8 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { ...@@ -3303,7 +3290,8 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
JSFunction::kPrototypeOrInitialMapOffset)); JSFunction::kPrototypeOrInitialMapOffset));
// Check that the function has a prototype or an initial map. // Check that the function has a prototype or an initial map.
__ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &deopt); DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex,
instr->environment());
// If the function does not have an initial map, we're done. // If the function does not have an initial map, we're done.
Label done; Label done;
...@@ -3318,11 +3306,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { ...@@ -3318,11 +3306,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
// map. // map.
__ Bind(&non_instance); __ Bind(&non_instance);
__ Ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); __ Ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
__ B(&done);
// Deoptimize case.
__ Bind(&deopt);
Deoptimize(instr->environment());
// All done. // All done.
__ Bind(&done); __ Bind(&done);
...@@ -3690,10 +3673,8 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { ...@@ -3690,10 +3673,8 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
: ToRegister32(instr->value()); : ToRegister32(instr->value());
Register result = r.IsSmi() ? ToRegister(instr->result()) Register result = r.IsSmi() ? ToRegister(instr->result())
: ToRegister32(instr->result()); : ToRegister32(instr->result());
Label done; __ Abs(result, input);
__ Abs(result, input, NULL, &done); DeoptimizeIf(vs, instr->environment());
Deoptimize(instr->environment());
__ Bind(&done);
} }
} }
...@@ -4224,26 +4205,17 @@ void LCodeGen::DoModI(LModI* instr) { ...@@ -4224,26 +4205,17 @@ void LCodeGen::DoModI(LModI* instr) {
Register divisor = ToRegister32(instr->right()); Register divisor = ToRegister32(instr->right());
Register result = ToRegister32(instr->result()); Register result = ToRegister32(instr->result());
Label deopt, done; Label done;
// modulo = dividend - quotient * divisor // modulo = dividend - quotient * divisor
__ Sdiv(result, dividend, divisor); __ Sdiv(result, dividend, divisor);
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
// Combine the deoptimization sites. DeoptimizeIfZero(divisor, instr->environment());
Label ok;
__ Cbnz(divisor, &ok);
__ Bind(&deopt);
Deoptimize(instr->environment());
__ Bind(&ok);
} }
__ Msub(result, result, divisor, dividend); __ Msub(result, result, divisor, dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ Cbnz(result, &done); __ Cbnz(result, &done);
if (deopt.is_bound()) { // TODO(all) This is a hack, remove this...
__ Tbnz(dividend, kWSignBit, &deopt);
} else {
DeoptimizeIfNegative(dividend, instr->environment()); DeoptimizeIfNegative(dividend, instr->environment());
} }
}
__ Bind(&done); __ Bind(&done);
} }
...@@ -5708,8 +5680,8 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { ...@@ -5708,8 +5680,8 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Register temp2 = ToRegister(instr->temp2()); Register temp2 = ToRegister(instr->temp2());
Label no_memento_found; Label no_memento_found;
__ JumpIfJSArrayHasAllocationMemento(object, temp1, temp2, &no_memento_found); __ TestJSArrayForAllocationMemento(object, temp1, temp2, &no_memento_found);
Deoptimize(instr->environment()); DeoptimizeIf(eq, instr->environment());
__ Bind(&no_memento_found); __ Bind(&no_memento_found);
} }
...@@ -5842,7 +5814,7 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { ...@@ -5842,7 +5814,7 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// If the receiver is null or undefined, we have to pass the global object as // If the receiver is null or undefined, we have to pass the global object as
// a receiver to normal functions. Values have to be passed unchanged to // a receiver to normal functions. Values have to be passed unchanged to
// builtins and strict-mode functions. // builtins and strict-mode functions.
Label global_object, done, deopt; Label global_object, done;
if (!instr->hydrogen()->known_function()) { if (!instr->hydrogen()->known_function()) {
__ Ldr(result, FieldMemOperand(function, __ Ldr(result, FieldMemOperand(function,
...@@ -5864,13 +5836,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { ...@@ -5864,13 +5836,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
__ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, &global_object); __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, &global_object);
// Deoptimize if the receiver is not a JS object. // Deoptimize if the receiver is not a JS object.
__ JumpIfSmi(receiver, &deopt); DeoptimizeIfSmi(receiver, instr->environment());
__ CompareObjectType(receiver, result, result, FIRST_SPEC_OBJECT_TYPE); __ CompareObjectType(receiver, result, result, FIRST_SPEC_OBJECT_TYPE);
__ Mov(result, receiver); __ Mov(result, receiver);
__ B(ge, &done); __ B(ge, &done);
// Otherwise, fall through to deopt.
__ Bind(&deopt);
Deoptimize(instr->environment()); Deoptimize(instr->environment());
__ Bind(&global_object); __ Bind(&global_object);
......
...@@ -503,7 +503,8 @@ class MacroAssembler : public Assembler { ...@@ -503,7 +503,8 @@ class MacroAssembler : public Assembler {
// Pseudo-instructions ------------------------------------------------------ // Pseudo-instructions ------------------------------------------------------
// Compute rd = abs(rm). // Compute rd = abs(rm).
// This function clobbers the condition flags. // This function clobbers the condition flags. On output the overflow flag is
// set iff the negation overflowed.
// //
// If rm is the minimum representable value, the result is not representable. // If rm is the minimum representable value, the result is not representable.
// Handlers for each case can be specified using the relevant labels. // Handlers for each case can be specified using the relevant labels.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment