| Index: src/compiler/bytecode-graph-builder.cc
|
| diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc
|
| index 5c81906a7e19bd664442c2e6e93a25902c03b8b9..8e6e40aa6332350c69aac17999834405d8991e19 100644
|
| --- a/src/compiler/bytecode-graph-builder.cc
|
| +++ b/src/compiler/bytecode-graph-builder.cc
|
| @@ -98,6 +98,42 @@ void BytecodeGraphBuilder::Environment::MarkAsUnreachable() {
|
| }
|
|
|
|
|
| +class BytecodeGraphBuilder::FrameStateBeforeAndAfter {
|
| + public:
|
| + explicit FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder)
|
| + : builder_(builder) {
|
| + // TODO(mythria): Replace with the actual frame state. Current
|
| + // implementation introduces empty frame state.
|
| + frame_state_before_ = builder_->jsgraph()->EmptyFrameState();
|
| + }
|
| +
|
| + void AddToNode(Node* node) {
|
| + int count = OperatorProperties::GetFrameStateInputCount(node->op());
|
| + DCHECK_LE(count, 2);
|
| + if (count >= 1) {
|
| + // Add the frame state for after the operation.
|
| + DCHECK_EQ(IrOpcode::kDead,
|
| + NodeProperties::GetFrameStateInput(node, 0)->opcode());
|
| +
|
| + // TODO(mythria): Replace with the actual frame state. Current
|
| + // implementation introduces empty frame state.
|
| + NodeProperties::ReplaceFrameStateInput(
|
| + node, 0, builder_->jsgraph()->EmptyFrameState());
|
| + }
|
| + if (count >= 2) {
|
| + // Add the frame state for before the operation.
|
| + DCHECK_EQ(IrOpcode::kDead,
|
| + NodeProperties::GetFrameStateInput(node, 1)->opcode());
|
| + NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
|
| + }
|
| + }
|
| +
|
| + private:
|
| + BytecodeGraphBuilder* builder_;
|
| + Node* frame_state_before_;
|
| +};
|
| +
|
| +
|
| BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
|
| CompilationInfo* compilation_info,
|
| JSGraph* jsgraph)
|
| @@ -123,6 +159,45 @@ Node* BytecodeGraphBuilder::GetFunctionContext() {
|
| }
|
|
|
|
|
| +Node* BytecodeGraphBuilder::GetFunctionClosure() {
|
| + if (!function_closure_.is_set()) {
|
| + const Operator* op = common()->Parameter(
|
| + Linkage::kJSFunctionCallClosureParamIndex, "%closure");
|
| + Node* node = NewNode(op, graph()->start());
|
| + function_closure_.set(node);
|
| + }
|
| + return function_closure_.get();
|
| +}
|
| +
|
| +
|
| +Node* BytecodeGraphBuilder::BuildLoadImmutableObjectField(Node* object,
|
| + int offset) {
|
| + return graph()->NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
|
| + jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
|
| + graph()->start(), graph()->start());
|
| +}
|
| +
|
| +
|
| +Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() {
|
| + if (!feedback_vector_.is_set()) {
|
| + Node* closure = GetFunctionClosure();
|
| + Node* shared = BuildLoadImmutableObjectField(
|
| + closure, JSFunction::kSharedFunctionInfoOffset);
|
| + Node* vector = BuildLoadImmutableObjectField(
|
| + shared, SharedFunctionInfo::kFeedbackVectorOffset);
|
| + feedback_vector_.set(vector);
|
| + }
|
| + return feedback_vector_.get();
|
| +}
|
| +
|
| +
|
| +VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
|
| + Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector();
|
| + FeedbackVectorSlot slot = feedback_vector->ToSlot(slot_id);
|
| + return VectorSlotPair(feedback_vector, slot);
|
| +}
|
| +
|
| +
|
| bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
|
| // Set up the basic structure of the graph. Outputs for {Start} are
|
| // the formal parameters (including the receiver) plus context and
|
| @@ -315,15 +390,32 @@ void BytecodeGraphBuilder::VisitStaContextSlot(
|
| }
|
|
|
|
|
| +void BytecodeGraphBuilder::BuildNamedLoad(
|
| + const interpreter::BytecodeArrayIterator& iterator) {
|
| + FrameStateBeforeAndAfter states(this);
|
| + Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
|
| + Handle<Name> name =
|
| + Handle<Name>::cast(iterator.GetConstantForIndexOperand(1));
|
| + VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));
|
| +
|
| + const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback);
|
| + Node* node = NewNode(op, object, BuildLoadFeedbackVector());
|
| + states.AddToNode(node);
|
| + environment()->BindAccumulator(node);
|
| +}
|
| +
|
| +
|
| void BytecodeGraphBuilder::VisitLoadICSloppy(
|
| const interpreter::BytecodeArrayIterator& iterator) {
|
| - UNIMPLEMENTED();
|
| + DCHECK(is_sloppy(language_mode()));
|
| + BuildNamedLoad(iterator);
|
| }
|
|
|
|
|
| void BytecodeGraphBuilder::VisitLoadICStrict(
|
| const interpreter::BytecodeArrayIterator& iterator) {
|
| - UNIMPLEMENTED();
|
| + DCHECK(is_strict(language_mode()));
|
| + BuildNamedLoad(iterator);
|
| }
|
|
|
|
|
| @@ -341,13 +433,15 @@ void BytecodeGraphBuilder::VisitKeyedLoadICStrict(
|
|
|
| void BytecodeGraphBuilder::VisitLoadICSloppyWide(
|
| const interpreter::BytecodeArrayIterator& iterator) {
|
| - UNIMPLEMENTED();
|
| + DCHECK(is_sloppy(language_mode()));
|
| + BuildNamedLoad(iterator);
|
| }
|
|
|
|
|
| void BytecodeGraphBuilder::VisitLoadICStrictWide(
|
| const interpreter::BytecodeArrayIterator& iterator) {
|
| - UNIMPLEMENTED();
|
| + DCHECK(is_strict(language_mode()));
|
| + BuildNamedLoad(iterator);
|
| }
|
|
|
|
|
|
|