CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
- CallDescriptor::Flags flags,
Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
- zone, function, parameter_count, properties, flags);
+ zone, function, parameter_count, properties);
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
- CallDescriptor::Flags flags,
Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
- zone, function, parameter_count, properties, flags);
+ zone, function, parameter_count, properties);
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
- CallDescriptor::Flags flags,
Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
- zone, function, parameter_count, properties, flags);
+ zone, function, parameter_count, properties);
}
bool pure) {
BinaryOpICStub stub(isolate(), Token::ADD); // TODO(mstarzinger): Hack.
CodeStubInterfaceDescriptor* d = stub.GetInterfaceDescriptor();
+ bool has_frame_state = OperatorProperties::HasFrameStateInput(node->op());
CallDescriptor* desc_compare = linkage()->GetStubCallDescriptor(
- d, 0, CallDescriptor::kPatchableCallSiteWithNop);
+ d, 0, CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node));
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), token);
- Node* compare;
+ NodeVector inputs(zone());
+ inputs.reserve(node->InputCount() + 1);
+ inputs.push_back(CodeConstant(ic));
+ inputs.push_back(NodeProperties::GetValueInput(node, 0));
+ inputs.push_back(NodeProperties::GetValueInput(node, 1));
+ inputs.push_back(NodeProperties::GetContextInput(node));
if (pure) {
- // A pure (strict) comparison doesn't have an effect or control.
- // But for the graph, we need to add these inputs.
- compare = graph()->NewNode(common()->Call(desc_compare), CodeConstant(ic),
- NodeProperties::GetValueInput(node, 0),
- NodeProperties::GetValueInput(node, 1),
- NodeProperties::GetContextInput(node),
- graph()->start(), graph()->start());
+ // A pure (strict) comparison doesn't have an effect, control or frame
+ // state. But for the graph, we need to add control and effect inputs.
+ DCHECK(!has_frame_state);
+ inputs.push_back(graph()->start());
+ inputs.push_back(graph()->start());
} else {
- compare = graph()->NewNode(common()->Call(desc_compare), CodeConstant(ic),
- NodeProperties::GetValueInput(node, 0),
- NodeProperties::GetValueInput(node, 1),
- NodeProperties::GetContextInput(node),
- NodeProperties::GetEffectInput(node),
- NodeProperties::GetControlInput(node));
+ DCHECK(has_frame_state == FLAG_turbo_deoptimization);
+ if (FLAG_turbo_deoptimization) {
+ inputs.push_back(NodeProperties::GetFrameStateInput(node));
+ }
+ inputs.push_back(NodeProperties::GetEffectInput(node));
+ inputs.push_back(NodeProperties::GetControlInput(node));
}
+ Node* compare = graph()->NewNode(common()->Call(desc_compare), inputs.size(),
+ &inputs.front());
+
node->ReplaceInput(0, compare);
node->ReplaceInput(1, SmiConstant(token));
+
+ if (has_frame_state) {
+ // Remove the frame state from inputs.
+ // TODO(jarin) This should use Node::RemoveInput (which does not exist yet).
+ int dest = NodeProperties::FirstFrameStateIndex(node);
+ for (int i = NodeProperties::PastFrameStateIndex(node);
+ i < node->InputCount(); i++) {
+ node->ReplaceInput(dest, node->InputAt(i));
+ dest++;
+ }
+ node->TrimInputCount(dest);
+ }
+
ReplaceWithRuntimeCall(node, Runtime::kBooleanize);
}
Operator::Property props = node->op()->properties();
const Runtime::Function* fun = Runtime::FunctionForId(f);
int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
- CallDescriptor* desc =
- linkage()->GetRuntimeCallDescriptor(f, nargs, props, FlagsForNode(node));
+ CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(f, nargs, props);
Node* ref = ExternalConstant(ExternalReference(f, isolate()));
Node* arity = Int32Constant(nargs);
if (!centrystub_constant_.is_set()) {
template <typename LinkageTraits>
static CallDescriptor* GetRuntimeCallDescriptor(
Zone* zone, Runtime::FunctionId function_id, int parameter_count,
- Operator::Property properties, CallDescriptor::Flags flags) {
+ Operator::Property properties) {
const int code_count = 1;
const int function_count = 1;
const int num_args_count = 1;
WordRegisterLocation(LinkageTraits::RuntimeCallArgCountReg());
locations[index++] = TaggedRegisterLocation(LinkageTraits::ContextReg());
+ CallDescriptor::Flags flags = Linkage::NeedsFrameState(function_id)
+ ? CallDescriptor::kNeedsFrameState
+ : CallDescriptor::kNoFlags;
+
// TODO(titzer): refactor TurboFan graph to consider context a value input.
return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject, // kind
return_count, // return_count
}
};
+
+bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
+ if (!FLAG_turbo_deoptimization) {
+ return false;
+ }
+ // TODO(jarin) At the moment, we only add frame state for
+ // few chosen runtime functions.
+ switch (function) {
+ case Runtime::kDebugBreak:
+ case Runtime::kDeoptimizeFunction:
+ case Runtime::kSetScriptBreakPoint:
+ case Runtime::kDebugGetLoadedScripts:
+ case Runtime::kStackGuard:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
}
-CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
- int parameter_count,
- Operator::Property properties,
- CallDescriptor::Flags flags) {
- return GetRuntimeCallDescriptor(function, parameter_count, properties, flags,
+CallDescriptor* Linkage::GetRuntimeCallDescriptor(
+ Runtime::FunctionId function, int parameter_count,
+ Operator::Property properties) {
+ return GetRuntimeCallDescriptor(function, parameter_count, properties,
this->info_->zone());
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
- CallDescriptor::Flags flags,
Zone* zone) {
UNIMPLEMENTED();
return NULL;
CallDescriptor* GetIncomingDescriptor() { return incoming_; }
CallDescriptor* GetJSCallDescriptor(int parameter_count);
static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone);
- CallDescriptor* GetRuntimeCallDescriptor(
- Runtime::FunctionId function, int parameter_count,
- Operator::Property properties,
- CallDescriptor::Flags flags = CallDescriptor::kNoFlags);
+ CallDescriptor* GetRuntimeCallDescriptor(Runtime::FunctionId function,
+ int parameter_count,
+ Operator::Property properties);
static CallDescriptor* GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
- CallDescriptor::Flags flags,
Zone* zone);
CallDescriptor* GetStubCallDescriptor(
CompilationInfo* info() const { return info_; }
+ static bool NeedsFrameState(Runtime::FunctionId function);
+
private:
CompilationInfo* info_;
CallDescriptor* incoming_;
}
switch (op->opcode()) {
- case IrOpcode::kJSCallFunction:
- case IrOpcode::kJSCallConstruct:
- return true;
case IrOpcode::kJSCallRuntime: {
Runtime::FunctionId function =
reinterpret_cast<Operator1<Runtime::FunctionId>*>(op)->parameter();
- // TODO(jarin) At the moment, we only add frame state for
- // few chosen runtime functions.
- switch (function) {
- case Runtime::kDebugBreak:
- case Runtime::kDeoptimizeFunction:
- case Runtime::kSetScriptBreakPoint:
- case Runtime::kDebugGetLoadedScripts:
- case Runtime::kStackGuard:
- return true;
- default:
- return false;
- }
- UNREACHABLE();
+ return Linkage::NeedsFrameState(function);
}
+ // Strict equality cannot lazily deoptimize.
+ case IrOpcode::kJSStrictEqual:
+ case IrOpcode::kJSStrictNotEqual:
+ return false;
+
+ // Calls
+ case IrOpcode::kJSCallFunction:
+ case IrOpcode::kJSCallConstruct:
+
+ // Compare operations
+ case IrOpcode::kJSEqual:
+ case IrOpcode::kJSNotEqual:
+ case IrOpcode::kJSLessThan:
+ case IrOpcode::kJSGreaterThan:
+ case IrOpcode::kJSLessThanOrEqual:
+ case IrOpcode::kJSGreaterThanOrEqual:
+
// Binary operations
case IrOpcode::kJSBitwiseOr:
case IrOpcode::kJSBitwiseXor:
Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
Node* arg0, Node* frame_state) {
CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
- function, 1, Operator::kNoProperties, CallDescriptor::kNeedsFrameState,
- zone());
+ function, 1, Operator::kNoProperties, zone());
Node* centry = HeapConstant(CEntryStub(isolate(), 1).GetCode());
Node* ref = NewNode(
effect_count + control_count;
CHECK_EQ(input_count, node->InputCount());
+ // Verify that frame state has been inserted for the nodes that need it.
+ if (OperatorProperties::HasFrameStateInput(node->op())) {
+ Node* frame_state = NodeProperties::GetFrameStateInput(node);
+ CHECK(frame_state->opcode() == IrOpcode::kFrameState);
+ CHECK(IsDefUseChainLinkPresent(frame_state, node));
+ CHECK(IsUseDefChainLinkPresent(frame_state, node));
+ }
+
// Verify all value inputs actually produce a value.
for (int i = 0; i < value_count; ++i) {
Node* value = NodeProperties::GetValueInput(node, i);
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
- CallDescriptor::Flags flags,
Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
- zone, function, parameter_count, properties, flags);
+ zone, function, parameter_count, properties);
}
'test-debug/ThreadedDebugging': [PASS, NO_VARIANTS],
'test-debug/DebugBreakLoop': [PASS, NO_VARIANTS],
- # Support for lazy deoptimization is missing.
- 'test-deoptimization/DeoptimizeCompare': [PASS, NO_VARIANTS],
-
# Support for breakpoints requires using LoadICs and StoreICs.
'test-debug/BreakPointICStore': [PASS, NO_VARIANTS],
'test-debug/BreakPointICLoad': [PASS, NO_VARIANTS],