| Index: src/compiler/js-intrinsic-lowering.cc
|
| diff --git a/src/compiler/js-intrinsic-lowering.cc b/src/compiler/js-intrinsic-lowering.cc
|
| index 2a3bdf8fa85bfe3dd54589852432fdefce70d93a..33a43f458b7592b9e393f73cdad857f8cd39ec8f 100644
|
| --- a/src/compiler/js-intrinsic-lowering.cc
|
| +++ b/src/compiler/js-intrinsic-lowering.cc
|
| @@ -84,6 +84,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
|
| return ReduceFixedArraySet(node);
|
| case Runtime::kInlineGetTypeFeedbackVector:
|
| return ReduceGetTypeFeedbackVector(node);
|
| + case Runtime::kInlineGetCallerJSFunction:
|
| + return ReduceGetCallerJSFunction(node);
|
| default:
|
| break;
|
| }
|
| @@ -455,6 +457,69 @@ Reduction JSIntrinsicLowering::ReduceGetTypeFeedbackVector(Node* node) {
|
| }
|
|
|
|
|
| +Reduction JSIntrinsicLowering::ReduceGetCallerJSFunction(Node* node) {
|
| + Node* effect = NodeProperties::GetEffectInput(node);
|
| + Node* control = NodeProperties::GetControlInput(node);
|
| +
|
| + if (FLAG_turbo_deoptimization) {
|
| + Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
|
| + Node* outer_frame = frame_state->InputAt(kFrameStateOuterStateInput);
|
| + if (outer_frame->opcode() == IrOpcode::kFrameState) {
|
| + FrameStateCallInfo state_info =
|
| + OpParameter<FrameStateCallInfo>(outer_frame);
|
| + switch (state_info.type()) {
|
| + case ARGUMENTS_ADAPTOR:
|
| + outer_frame = outer_frame->InputAt(kFrameStateOuterStateInput);
|
| + DCHECK(outer_frame->opcode() == IrOpcode::kFrameState);
|
| + DCHECK(OpParameter<FrameStateCallInfo>(frame_state).type() ==
|
| + JS_FRAME);
|
| + break;
|
| + case JS_FRAME:
|
| + break;
|
| + }
|
| + // The intrinsic is inlined, return the function from the outer frame.
|
| + Node* outer_function = outer_frame->InputAt(kFrameStateFunctionInput);
|
| + AdvancedReducer::ReplaceWithValue(node, outer_function, effect, control);
|
| + return Changed(outer_function);
|
| + }
|
| + }
|
| +
|
| + // TODO(danno): If FLAG_turbo_deoptimization is false then this intrinsic
|
| + // always returns the JSFunction from the caller's frame, regardless of
|
| + // inlining depth, which isn't correct. This implementation also forces
|
| + // intrinsic lowering to happen after inlining, which is fine for now, but
|
| + // eventually the frame-querying logic probably should go later, e.g. in
|
| + // instruction selection, so that there is no phase-ordering dependency.
|
| + FieldAccess access = AccessBuilder::ForFrameCallerFramePtr();
|
| + Node* fp = graph()->NewNode(machine()->LoadFramePointer());
|
| + Node* next_fp =
|
| + graph()->NewNode(simplified()->LoadField(access), fp, effect, control);
|
| + Node* candidate = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForFrameContext()), next_fp,
|
| + effect, control);
|
| +
|
| + // If JSFunction from the outermost frame is a SMI, then the frame is
|
| + // either an arguments adapter or construct frame and needs to be skipped.
|
| + Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), candidate);
|
| + Node* branch = graph()->NewNode(common()->Branch(), check, control);
|
| +
|
| + Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
| +
|
| + Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
| +
|
| + Node* next_next_fp = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForFrameCallerFramePtr()), next_fp,
|
| + next_fp, control);
|
| +
|
| + MachineType const type = static_cast<MachineType>(kMachPtr);
|
| + control = graph()->NewNode(common()->Merge(2), if_true, if_false);
|
| + next_fp =
|
| + graph()->NewNode(common()->Phi(type, 2), next_next_fp, next_fp, control);
|
| + return Change(node, simplified()->LoadField(AccessBuilder::ForFrameMarker()),
|
| + next_fp, effect, control);
|
| +}
|
| +
|
| +
|
| Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
|
| Node* b) {
|
| node->set_op(op);
|
|
|