[turbofan] Remove frame-state from {JSConvertReceiver}.

The operator in question does not call arbitrary JavaSciprt, nor throw,
nor trigger a lazy deoptimization. Nodes hence do not need a frame-state
representing the "after" state of the operation.

R=bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/2672763002
Cr-Commit-Position: refs/heads/master@{#42891}
This commit is contained in:
mstarzinger 2017-02-02 06:00:07 -08:00 committed by Commit bot
parent 2baea747de
commit d0edd08eb5
4 changed files with 16 additions and 22 deletions

View File

@ -600,20 +600,15 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
Node* context = jsgraph()->Constant(handle(function->context()));
// Insert a JSConvertReceiver node for sloppy callees. Note that the context
// passed into this node has to be the callees context (loaded above). Note
// that the frame state passed to the JSConvertReceiver must be the frame
// state _before_ the call; it is not necessary to fiddle with the receiver
// in that frame state tho, as the conversion of the receiver can be repeated
// any number of times, it's not observable.
// passed into this node has to be the callees context (loaded above).
if (node->opcode() == IrOpcode::kJSCall &&
is_sloppy(shared_info->language_mode()) && !shared_info->native()) {
Node* effect = NodeProperties::GetEffectInput(node);
if (NeedsConvertReceiver(call.receiver(), effect)) {
const CallParameters& p = CallParametersOf(node->op());
Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
Node* convert = effect = graph()->NewNode(
javascript()->ConvertReceiver(p.convert_mode()), call.receiver(),
context, frame_state_before, effect, start);
Node* convert = effect =
graph()->NewNode(javascript()->ConvertReceiver(p.convert_mode()),
call.receiver(), context, effect, start);
NodeProperties::ReplaceValueInput(node, convert, 1);
NodeProperties::ReplaceEffectInput(node, effect);
}

View File

@ -1715,7 +1715,6 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
Type* receiver_type = NodeProperties::GetType(receiver);
Node* context = NodeProperties::GetContextInput(node);
Type* context_type = NodeProperties::GetType(context);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
@ -1762,14 +1761,15 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
Node* efalse = effect;
Node* rfalse;
{
// Convert {receiver} using the ToObjectStub.
// Convert {receiver} using the ToObjectStub. The call does not require a
// frame-state in this case, because neither null nor undefined is passed.
Callable callable = CodeFactory::ToObject(isolate());
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, node->op()->properties());
CallDescriptor::kNoFlags, node->op()->properties());
rfalse = efalse = graph()->NewNode(
common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
receiver, context, frame_state, efalse);
receiver, context, efalse);
}
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
@ -1819,14 +1819,15 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
Node* econvert = effect;
Node* rconvert;
{
// Convert {receiver} using the ToObjectStub.
// Convert {receiver} using the ToObjectStub. The call does not require a
// frame-state in this case, because neither null nor undefined is passed.
Callable callable = CodeFactory::ToObject(isolate());
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, node->op()->properties());
CallDescriptor::kNoFlags, node->op()->properties());
rconvert = econvert = graph()->NewNode(
common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
receiver, context, frame_state, econvert);
receiver, context, econvert);
}
// Replace {receiver} with global proxy of {context}.
@ -2063,7 +2064,6 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) {
Type* receiver_type = NodeProperties::GetType(receiver);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Try to infer receiver {convert_mode} from {receiver} type.
if (receiver_type->Is(Type::NullOrUndefined())) {
@ -2096,7 +2096,7 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) {
!receiver_type->Is(Type::Receiver())) {
receiver = effect =
graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
receiver, context, frame_state, effect, control);
receiver, context, effect, control);
NodeProperties::ReplaceValueInput(node, receiver, 1);
}

View File

@ -142,11 +142,11 @@ CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) {
bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
switch (function) {
// Most runtime functions need a FrameState. A few chosen ones that we know
// not to call into arbitrary JavaScript, not to throw, and not to
// deoptimize
// are whitelisted here and can be called without a FrameState.
// not to call into arbitrary JavaScript, not to throw, and not to lazily
// deoptimize are whitelisted here and can be called without a FrameState.
case Runtime::kAbort:
case Runtime::kAllocateInTargetSpace:
case Runtime::kConvertReceiver:
case Runtime::kCreateIterResultObject:
case Runtime::kDefineGetterPropertyUnchecked: // TODO(jarin): Is it safe?
case Runtime::kDefineSetterPropertyUnchecked: // TODO(jarin): Is it safe?

View File

@ -100,7 +100,6 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kJSCallWithSpread:
// Misc operations
case IrOpcode::kJSConvertReceiver:
case IrOpcode::kJSForInNext:
case IrOpcode::kJSForInPrepare:
case IrOpcode::kJSStackCheck: