// 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.
#include "src/compiler/js-frame-specialization.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/frames-inl.h"
namespace v8 {
namespace internal {
namespace compiler {
Reduction JSFrameSpecialization::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kOsrValue:
return ReduceOsrValue(node);
case IrOpcode::kOsrGuard:
return ReduceOsrGuard(node);
case IrOpcode::kParameter:
return ReduceParameter(node);
default:
break;
}
return NoChange();
}
Reduction JSFrameSpecialization::ReduceOsrValue(Node* node) {
// JSFrameSpecialization should never run on interpreted frames, since the
// code below assumes standard stack frame layouts.
DCHECK(!frame()->is_interpreted());
DCHECK_EQ(IrOpcode::kOsrValue, node->opcode());
Handle<Object> value;
int index = OsrValueIndexOf(node->op());
int const parameters_count = frame()->ComputeParametersCount() + 1;
if (index == Linkage::kOsrContextSpillSlotIndex) {
value = handle(frame()->context(), isolate());
} else if (index >= parameters_count) {
value = handle(frame()->GetExpression(index - parameters_count), isolate());
} else {
// The OsrValue index 0 is the receiver.
value =
handle(index ? frame()->GetParameter(index - 1) : frame()->receiver(),
isolate());
}
return Replace(jsgraph()->Constant(value));
}
Reduction JSFrameSpecialization::ReduceOsrGuard(Node* node) {
DCHECK_EQ(IrOpcode::kOsrGuard, node->opcode());
ReplaceWithValue(node, node->InputAt(0),
NodeProperties::GetEffectInput(node));
return Changed(node);
}
Reduction JSFrameSpecialization::ReduceParameter(Node* node) {
DCHECK_EQ(IrOpcode::kParameter, node->opcode());
Handle<Object> value;
int const index = ParameterIndexOf(node->op());
int const parameters_count = frame()->ComputeParametersCount() + 1;
if (index == Linkage::kJSCallClosureParamIndex) {
// The Parameter index references the closure.
value = handle(frame()->function(), isolate());
} else if (index == Linkage::GetJSCallArgCountParamIndex(parameters_count)) {
// The Parameter index references the parameter count.
value = handle(Smi::FromInt(parameters_count - 1), isolate());
} else if (index == Linkage::GetJSCallContextParamIndex(parameters_count)) {
// The Parameter index references the context.
value = handle(frame()->context(), isolate());
} else {
// The Parameter index 0 is the receiver.
value =
handle(index ? frame()->GetParameter(index - 1) : frame()->receiver(),
isolate());
}
return Replace(jsgraph()->Constant(value));
}
Isolate* JSFrameSpecialization::isolate() const { return jsgraph()->isolate(); }
} // namespace compiler
} // namespace internal
} // namespace v8