Commit f9a9c6be authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Introduce lazy bailout, masked as a call.

This introduces an explicit lazy bailout. It is wrapped in the call
node, mostly because the lazy deoptimization processing is married
to the call processing in the instruction selector and the code generator.

It is still a terrible hack.

R=bmeurer@chromium.org,mstarzinger@chromium.org
BUG=chromium:543994,v8:4195
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#31353}
parent e1088b27
...@@ -384,6 +384,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -384,6 +384,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, kScratchReg); __ PrepareCallCFunction(num_parameters, kScratchReg);
......
...@@ -1164,7 +1164,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1164,7 +1164,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -1177,9 +1177,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1177,9 +1177,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
// Emit the call instruction. // Emit the call instruction.
......
...@@ -477,6 +477,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -477,6 +477,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Jump(x10); __ Jump(x10);
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: case kArchPrepareCallCFunction:
// We don't need kArchPrepareCallCFunction on arm64 as the instruction // We don't need kArchPrepareCallCFunction on arm64 as the instruction
// selector already perform a Claim to reserve space on the stack and // selector already perform a Claim to reserve space on the stack and
......
...@@ -1477,7 +1477,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1477,7 +1477,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -1490,9 +1490,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1490,9 +1490,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
// Emit the call instruction. // Emit the call instruction.
......
...@@ -1410,10 +1410,13 @@ void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { ...@@ -1410,10 +1410,13 @@ void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
} }
try_control.EndTry(); try_control.EndTry();
// TODO(mstarzinger): We are only using a runtime call to get a lazy bailout // Insert lazy bailout point.
// point, there is no need to really emit an actual call. Optimize this! // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout
Node* guard = NewNode(javascript()->CallRuntime(Runtime::kMaxSmi, 0)); // point. Ideally, we whould not re-enter optimized code when deoptimized
PrepareFrameState(guard, stmt->HandlerId()); // lazily. Tracked by issue v8:4195.
NewNode(common()->LazyBailout(),
jsgraph()->ZeroConstant(), // dummy target.
environment()->Checkpoint(stmt->HandlerId())); // frame state.
// Clear message object as we enter the catch block. // Clear message object as we enter the catch block.
Node* the_hole = jsgraph()->TheHoleConstant(); Node* the_hole = jsgraph()->TheHoleConstant();
...@@ -1461,10 +1464,13 @@ void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { ...@@ -1461,10 +1464,13 @@ void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
} }
try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result); try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
// TODO(mstarzinger): We are only using a runtime call to get a lazy bailout // Insert lazy bailout point.
// point, there is no need to really emit an actual call. Optimize this! // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout
Node* guard = NewNode(javascript()->CallRuntime(Runtime::kMaxSmi, 0)); // point. Ideally, we whould not re-enter optimized code when deoptimized
PrepareFrameState(guard, stmt->HandlerId()); // lazily. Tracked by issue v8:4195.
NewNode(common()->LazyBailout(),
jsgraph()->ZeroConstant(), // dummy target.
environment()->Checkpoint(stmt->HandlerId())); // frame state.
// The result value semantics depend on how the block was entered: // The result value semantics depend on how the block was entered:
// - ReturnStatement: It represents the return value being returned. // - ReturnStatement: It represents the return value being returned.
......
...@@ -740,6 +740,11 @@ const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) { ...@@ -740,6 +740,11 @@ const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
} }
const Operator* CommonOperatorBuilder::LazyBailout() {
return Call(Linkage::GetLazyBailoutDescriptor(zone()));
}
const Operator* CommonOperatorBuilder::TailCall( const Operator* CommonOperatorBuilder::TailCall(
const CallDescriptor* descriptor) { const CallDescriptor* descriptor) {
class TailCallOperator final : public Operator1<const CallDescriptor*> { class TailCallOperator final : public Operator1<const CallDescriptor*> {
......
...@@ -155,6 +155,7 @@ class CommonOperatorBuilder final : public ZoneObject { ...@@ -155,6 +155,7 @@ class CommonOperatorBuilder final : public ZoneObject {
const Operator* Call(const CallDescriptor* descriptor); const Operator* Call(const CallDescriptor* descriptor);
const Operator* TailCall(const CallDescriptor* descriptor); const Operator* TailCall(const CallDescriptor* descriptor);
const Operator* Projection(size_t index); const Operator* Projection(size_t index);
const Operator* LazyBailout();
// Constructs a new merge or phi operator with the same opcode as {op}, but // Constructs a new merge or phi operator with the same opcode as {op}, but
// with {size} inputs. // with {size} inputs.
......
...@@ -349,6 +349,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -349,6 +349,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, i.TempRegister(0)); __ PrepareCallCFunction(num_parameters, i.TempRegister(0));
......
...@@ -907,7 +907,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -907,7 +907,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -920,9 +920,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -920,9 +920,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
// Emit the call instruction. // Emit the call instruction.
......
...@@ -42,6 +42,7 @@ namespace compiler { ...@@ -42,6 +42,7 @@ namespace compiler {
V(ArchTailCallJSFunction) \ V(ArchTailCallJSFunction) \
V(ArchPrepareCallCFunction) \ V(ArchPrepareCallCFunction) \
V(ArchCallCFunction) \ V(ArchCallCFunction) \
V(ArchLazyBailout) \
V(ArchJmp) \ V(ArchJmp) \
V(ArchLookupSwitch) \ V(ArchLookupSwitch) \
V(ArchTableSwitch) \ V(ArchTableSwitch) \
......
...@@ -345,6 +345,10 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, ...@@ -345,6 +345,10 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
g.UseLocation(callee, buffer->descriptor->GetInputLocation(0), g.UseLocation(callee, buffer->descriptor->GetInputLocation(0),
buffer->descriptor->GetInputType(0))); buffer->descriptor->GetInputType(0)));
break; break;
case CallDescriptor::kLazyBailout:
// The target is ignored, but we still need to pass a value here.
buffer->instruction_args.push_back(g.UseImmediate(callee));
break;
} }
DCHECK_EQ(1u, buffer->instruction_args.size()); DCHECK_EQ(1u, buffer->instruction_args.size());
......
...@@ -63,6 +63,9 @@ std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) { ...@@ -63,6 +63,9 @@ std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
os << "Addr"; os << "Addr";
break; break;
case CallDescriptor::kLazyBailout:
os << "LazyBail";
break;
} }
return os; return os;
} }
...@@ -351,6 +354,31 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor( ...@@ -351,6 +354,31 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
} }
CallDescriptor* Linkage::GetLazyBailoutDescriptor(Zone* zone) {
const size_t return_count = 0;
const size_t parameter_count = 0;
LocationSignature::Builder locations(zone, return_count, parameter_count);
MachineSignature::Builder types(zone, return_count, parameter_count);
// The target is ignored, but we need to give some values here.
MachineType target_type = kMachAnyTagged;
LinkageLocation target_loc = regloc(kJSFunctionRegister);
return new (zone) CallDescriptor( // --
CallDescriptor::kLazyBailout, // kind
target_type, // target MachineType
target_loc, // target location
types.Build(), // machine_sig
locations.Build(), // location_sig
0, // stack_parameter_count
Operator::kNoThrow, // properties
kNoCalleeSaved, // callee-saved
kNoCalleeSaved, // callee-saved fp
CallDescriptor::kNeedsFrameState, // flags
"lazy-bailout");
}
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr, CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int js_parameter_count, int js_parameter_count,
CallDescriptor::Flags flags) { CallDescriptor::Flags flags) {
......
...@@ -110,9 +110,10 @@ class CallDescriptor final : public ZoneObject { ...@@ -110,9 +110,10 @@ class CallDescriptor final : public ZoneObject {
public: public:
// Describes the kind of this call, which determines the target. // Describes the kind of this call, which determines the target.
enum Kind { enum Kind {
kCallCodeObject, // target is a Code object kCallCodeObject, // target is a Code object
kCallJSFunction, // target is a JSFunction object kCallJSFunction, // target is a JSFunction object
kCallAddress, // target is a machine pointer kCallAddress, // target is a machine pointer
kLazyBailout // the call is no-op, only used for lazy bailout
}; };
enum Flag { enum Flag {
...@@ -271,10 +272,13 @@ class Linkage : public ZoneObject { ...@@ -271,10 +272,13 @@ class Linkage : public ZoneObject {
static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr, static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count, int parameter_count,
CallDescriptor::Flags flags); CallDescriptor::Flags flags);
static CallDescriptor* GetRuntimeCallDescriptor( static CallDescriptor* GetRuntimeCallDescriptor(
Zone* zone, Runtime::FunctionId function, int parameter_count, Zone* zone, Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, bool needs_frame_state = true); Operator::Properties properties, bool needs_frame_state = true);
static CallDescriptor* GetLazyBailoutDescriptor(Zone* zone);
static CallDescriptor* GetStubCallDescriptor( static CallDescriptor* GetStubCallDescriptor(
Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor, Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
int stack_parameter_count, CallDescriptor::Flags flags, int stack_parameter_count, CallDescriptor::Flags flags,
......
...@@ -457,6 +457,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -457,6 +457,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Jump(at); __ Jump(at);
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, kScratchReg); __ PrepareCallCFunction(num_parameters, kScratchReg);
......
...@@ -584,7 +584,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -584,7 +584,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -597,9 +597,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -597,9 +597,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
// Emit the call instruction. // Emit the call instruction.
......
...@@ -455,6 +455,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -455,6 +455,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Jump(at); __ Jump(at);
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, kScratchReg); __ PrepareCallCFunction(num_parameters, kScratchReg);
......
...@@ -771,7 +771,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -771,7 +771,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -784,9 +784,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -784,9 +784,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
opcode |= MiscField::encode(flags); opcode |= MiscField::encode(flags);
......
...@@ -654,6 +654,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -654,6 +654,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
DCHECK_EQ(LeaveRC, i.OutputRCBit()); DCHECK_EQ(LeaveRC, i.OutputRCBit());
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, kScratchReg); __ PrepareCallCFunction(num_parameters, kScratchReg);
......
...@@ -1545,7 +1545,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1545,7 +1545,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -1558,9 +1558,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1558,9 +1558,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
// Emit the call instruction. // Emit the call instruction.
......
...@@ -596,6 +596,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -596,6 +596,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters); __ PrepareCallCFunction(num_parameters);
......
...@@ -1132,7 +1132,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1132,7 +1132,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -1145,9 +1145,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -1145,9 +1145,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
// Emit the call instruction. // Emit the call instruction.
......
...@@ -379,6 +379,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -379,6 +379,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
break; break;
} }
case kArchLazyBailout: {
EnsureSpaceForLazyDeopt();
RecordCallPosition(instr);
break;
}
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, i.TempRegister(0)); __ PrepareCallCFunction(num_parameters, i.TempRegister(0));
......
...@@ -897,7 +897,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -897,7 +897,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
} }
// Select the appropriate opcode based on the call type. // Select the appropriate opcode based on the call type.
InstructionCode opcode; InstructionCode opcode = kArchNop;
switch (descriptor->kind()) { switch (descriptor->kind()) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = opcode =
...@@ -910,9 +910,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -910,9 +910,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
default: case CallDescriptor::kLazyBailout:
UNREACHABLE(); opcode = kArchLazyBailout | MiscField::encode(flags);
return; break;
} }
// Emit the call instruction. // Emit the call instruction.
......
...@@ -152,9 +152,6 @@ ...@@ -152,9 +152,6 @@
# TODO(titzer): too slow in --turbo mode due to O(n^2) graph verification. # TODO(titzer): too slow in --turbo mode due to O(n^2) graph verification.
'regress/regress-1122': [PASS, NO_VARIANTS], 'regress/regress-1122': [PASS, NO_VARIANTS],
# TODO(mstarzinger): try..catch and lazy deopts don't seem to work correctly.
'regress/regress-crbug-450960': [PASS, NO_VARIANTS],
# issue 4078: # issue 4078:
'allocation-site-info': [PASS, NO_VARIANTS], 'allocation-site-info': [PASS, NO_VARIANTS],
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flass: --allow-natives-syntax --always-opt --gc-interval=163 --stress-compaction
try { a = f();
} catch(e) {
}
var i = 0;
function f() {
try {
f();
} catch(e) {
i++;
[];
}
}
f();
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