2015-09-10 16:21:34 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
#ifndef V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
|
|
|
|
#define V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
|
|
|
|
|
2016-11-22 18:05:03 +00:00
|
|
|
#include "src/compiler/bytecode-analysis.h"
|
2015-09-10 16:21:34 +00:00
|
|
|
#include "src/compiler/js-graph.h"
|
2016-09-07 13:00:04 +00:00
|
|
|
#include "src/compiler/liveness-analyzer.h"
|
|
|
|
#include "src/compiler/state-values-utils.h"
|
2015-09-10 16:21:34 +00:00
|
|
|
#include "src/interpreter/bytecode-array-iterator.h"
|
2016-07-15 12:03:04 +00:00
|
|
|
#include "src/interpreter/bytecode-flags.h"
|
2015-09-10 16:21:34 +00:00
|
|
|
#include "src/interpreter/bytecodes.h"
|
2016-10-13 13:13:59 +00:00
|
|
|
#include "src/source-position-table.h"
|
2015-09-10 16:21:34 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
2016-08-31 08:49:14 +00:00
|
|
|
|
|
|
|
class CompilationInfo;
|
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
namespace compiler {
|
|
|
|
|
This CL enables precise source positions for all V8 compilers. It merges compiler::SourcePosition and internal::SourcePosition to a single class used throughout the codebase. The new internal::SourcePosition instances store an id identifying an inlined function in addition to a script offset.
SourcePosition::InliningId() refers to a the new table DeoptimizationInputData::InliningPositions(), which provides the following data for every inlining id:
- The inlined SharedFunctionInfo as an offset into DeoptimizationInfo::LiteralArray
- The SourcePosition of the inlining. Recursively, this yields the full inlining stack.
Before the Code object is created, the same information can be found in CompilationInfo::inlined_functions().
If SourcePosition::InliningId() is SourcePosition::kNotInlined, it refers to the outer (non-inlined) function.
So every SourcePosition has full information about its inlining stack, as long as the corresponding Code object is known. The internal represenation of a source position is a positive 64bit integer.
All compilers create now appropriate source positions for inlined functions. In the case of Turbofan, this required using AstGraphBuilderWithPositions for inlined functions too. So this class is now moved to a header file.
At the moment, the additional information in source positions is only used in --trace-deopt and --code-comments. The profiler needs to be updated, at the moment it gets the correct script offsets from the deopt info, but the wrong script id from the reconstructed deopt stack, which can lead to wrong outputs. This should be resolved by making the profiler use the new inlining information for deopts.
I activated the inlined deoptimization tests in test-cpu-profiler.cc for Turbofan, changing them to a case where the deopt stack and the inlining position agree. It is currently still broken for other cases.
The following additional changes were necessary:
- The source position table (internal::SourcePositionTableBuilder etc.) supports now 64bit source positions. Encoding source positions in a single 64bit int together with the difference encoding in the source position table results in very little overhead for the inlining id, since only 12% of the source positions in Octane have a changed inlining id.
- The class HPositionInfo was effectively dead code and is now removed.
- SourcePosition has new printing and information facilities, including computing a full inlining stack.
- I had to rename compiler/source-position.{h,cc} to compiler/compiler-source-position-table.{h,cc} to avoid clashes with the new src/source-position.cc file.
- I wrote the new wrapper PodArray for ByteArray. It is a template working with any POD-type. This is used in DeoptimizationInputData::InliningPositions().
- I removed HInlinedFunctionInfo and HGraph::inlined_function_infos, because they were only used for the now obsolete Crankshaft inlining ids.
- Crankshaft managed a list of inlined functions in Lithium: LChunk::inlined_functions. This is an analog structure to CompilationInfo::inlined_functions. So I removed LChunk::inlined_functions and made Crankshaft use CompilationInfo::inlined_functions instead, because this was necessary to register the offsets into the literal array in a uniform way. This is a safe change because LChunk::inlined_functions has no other uses and the functions in CompilationInfo::inlined_functions have a strictly longer lifespan, being created earlier (in Hydrogen already).
BUG=v8:5432
Review-Url: https://codereview.chromium.org/2451853002
Cr-Commit-Position: refs/heads/master@{#40975}
2016-11-14 17:21:37 +00:00
|
|
|
class SourcePositionTable;
|
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
// The BytecodeGraphBuilder produces a high-level IR graph based on
|
|
|
|
// interpreter bytecodes.
|
|
|
|
class BytecodeGraphBuilder {
|
|
|
|
public:
|
|
|
|
BytecodeGraphBuilder(Zone* local_zone, CompilationInfo* info,
|
2016-10-13 13:13:59 +00:00
|
|
|
JSGraph* jsgraph, float invocation_frequency,
|
This CL enables precise source positions for all V8 compilers. It merges compiler::SourcePosition and internal::SourcePosition to a single class used throughout the codebase. The new internal::SourcePosition instances store an id identifying an inlined function in addition to a script offset.
SourcePosition::InliningId() refers to a the new table DeoptimizationInputData::InliningPositions(), which provides the following data for every inlining id:
- The inlined SharedFunctionInfo as an offset into DeoptimizationInfo::LiteralArray
- The SourcePosition of the inlining. Recursively, this yields the full inlining stack.
Before the Code object is created, the same information can be found in CompilationInfo::inlined_functions().
If SourcePosition::InliningId() is SourcePosition::kNotInlined, it refers to the outer (non-inlined) function.
So every SourcePosition has full information about its inlining stack, as long as the corresponding Code object is known. The internal represenation of a source position is a positive 64bit integer.
All compilers create now appropriate source positions for inlined functions. In the case of Turbofan, this required using AstGraphBuilderWithPositions for inlined functions too. So this class is now moved to a header file.
At the moment, the additional information in source positions is only used in --trace-deopt and --code-comments. The profiler needs to be updated, at the moment it gets the correct script offsets from the deopt info, but the wrong script id from the reconstructed deopt stack, which can lead to wrong outputs. This should be resolved by making the profiler use the new inlining information for deopts.
I activated the inlined deoptimization tests in test-cpu-profiler.cc for Turbofan, changing them to a case where the deopt stack and the inlining position agree. It is currently still broken for other cases.
The following additional changes were necessary:
- The source position table (internal::SourcePositionTableBuilder etc.) supports now 64bit source positions. Encoding source positions in a single 64bit int together with the difference encoding in the source position table results in very little overhead for the inlining id, since only 12% of the source positions in Octane have a changed inlining id.
- The class HPositionInfo was effectively dead code and is now removed.
- SourcePosition has new printing and information facilities, including computing a full inlining stack.
- I had to rename compiler/source-position.{h,cc} to compiler/compiler-source-position-table.{h,cc} to avoid clashes with the new src/source-position.cc file.
- I wrote the new wrapper PodArray for ByteArray. It is a template working with any POD-type. This is used in DeoptimizationInputData::InliningPositions().
- I removed HInlinedFunctionInfo and HGraph::inlined_function_infos, because they were only used for the now obsolete Crankshaft inlining ids.
- Crankshaft managed a list of inlined functions in Lithium: LChunk::inlined_functions. This is an analog structure to CompilationInfo::inlined_functions. So I removed LChunk::inlined_functions and made Crankshaft use CompilationInfo::inlined_functions instead, because this was necessary to register the offsets into the literal array in a uniform way. This is a safe change because LChunk::inlined_functions has no other uses and the functions in CompilationInfo::inlined_functions have a strictly longer lifespan, being created earlier (in Hydrogen already).
BUG=v8:5432
Review-Url: https://codereview.chromium.org/2451853002
Cr-Commit-Position: refs/heads/master@{#40975}
2016-11-14 17:21:37 +00:00
|
|
|
SourcePositionTable* source_positions,
|
|
|
|
int inlining_id = SourcePosition::kNotInlined);
|
2015-09-10 16:21:34 +00:00
|
|
|
|
|
|
|
// Creates a graph by visiting bytecodes.
|
2016-11-03 10:21:05 +00:00
|
|
|
bool CreateGraph(bool stack_check = true);
|
2015-09-10 16:21:34 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
class Environment;
|
|
|
|
|
2016-11-03 10:21:05 +00:00
|
|
|
void VisitBytecodes(bool stack_check);
|
2015-09-10 16:21:34 +00:00
|
|
|
|
2015-11-17 09:05:37 +00:00
|
|
|
// Get or create the node that represents the outer function closure.
|
|
|
|
Node* GetFunctionClosure();
|
|
|
|
|
|
|
|
// Get or create the node that represents the outer function context.
|
2015-09-10 16:21:34 +00:00
|
|
|
Node* GetFunctionContext();
|
|
|
|
|
2015-12-01 17:28:43 +00:00
|
|
|
// Get or create the node that represents the incoming new target value.
|
|
|
|
Node* GetNewTarget();
|
2015-11-17 09:05:37 +00:00
|
|
|
|
2015-11-20 09:25:13 +00:00
|
|
|
// Builder for loading the a native context field.
|
|
|
|
Node* BuildLoadNativeContextField(int index);
|
|
|
|
|
2015-11-17 09:05:37 +00:00
|
|
|
// Helper function for creating a pair containing type feedback vector and
|
|
|
|
// a feedback slot.
|
|
|
|
VectorSlotPair CreateVectorSlotPair(int slot_id);
|
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
void set_environment(Environment* env) { environment_ = env; }
|
|
|
|
const Environment* environment() const { return environment_; }
|
|
|
|
Environment* environment() { return environment_; }
|
|
|
|
|
|
|
|
// Node creation helpers
|
|
|
|
Node* NewNode(const Operator* op, bool incomplete = false) {
|
2016-01-11 12:56:50 +00:00
|
|
|
return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
|
2015-09-10 16:21:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Node* NewNode(const Operator* op, Node* n1) {
|
|
|
|
Node* buffer[] = {n1};
|
|
|
|
return MakeNode(op, arraysize(buffer), buffer, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* NewNode(const Operator* op, Node* n1, Node* n2) {
|
|
|
|
Node* buffer[] = {n1, n2};
|
|
|
|
return MakeNode(op, arraysize(buffer), buffer, false);
|
|
|
|
}
|
|
|
|
|
2015-11-17 09:05:37 +00:00
|
|
|
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
|
|
|
|
Node* buffer[] = {n1, n2, n3};
|
|
|
|
return MakeNode(op, arraysize(buffer), buffer, false);
|
|
|
|
}
|
|
|
|
|
2015-11-19 14:16:36 +00:00
|
|
|
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
|
|
|
|
Node* buffer[] = {n1, n2, n3, n4};
|
|
|
|
return MakeNode(op, arraysize(buffer), buffer, false);
|
|
|
|
}
|
|
|
|
|
2016-11-18 12:13:30 +00:00
|
|
|
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
|
|
|
|
Node* n5) {
|
|
|
|
Node* buffer[] = {n1, n2, n3, n4, n5};
|
|
|
|
return MakeNode(op, arraysize(buffer), buffer, false);
|
|
|
|
}
|
|
|
|
|
2015-12-16 16:29:09 +00:00
|
|
|
// Helpers to create new control nodes.
|
|
|
|
Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
|
|
|
|
Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
|
|
|
|
Node* NewMerge() { return NewNode(common()->Merge(1), true); }
|
|
|
|
Node* NewLoop() { return NewNode(common()->Loop(1), true); }
|
|
|
|
Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
|
|
|
|
return NewNode(common()->Branch(hint), condition);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates a new Phi node having {count} input values.
|
|
|
|
Node* NewPhi(int count, Node* input, Node* control);
|
|
|
|
Node* NewEffectPhi(int count, Node* input, Node* control);
|
2015-09-10 16:21:34 +00:00
|
|
|
|
2015-12-16 16:29:09 +00:00
|
|
|
// Helpers for merging control, effect or value dependencies.
|
2015-09-10 16:21:34 +00:00
|
|
|
Node* MergeControl(Node* control, Node* other);
|
2015-12-16 16:29:09 +00:00
|
|
|
Node* MergeEffect(Node* effect, Node* other_effect, Node* control);
|
|
|
|
Node* MergeValue(Node* value, Node* other_value, Node* control);
|
2015-09-10 16:21:34 +00:00
|
|
|
|
2015-12-16 16:29:09 +00:00
|
|
|
// The main node creation chokepoint. Adds context, frame state, effect,
|
|
|
|
// and control dependencies depending on the operator.
|
|
|
|
Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
|
|
|
|
bool incomplete);
|
2015-09-10 16:21:34 +00:00
|
|
|
|
2015-12-16 16:29:09 +00:00
|
|
|
Node** EnsureInputBufferSize(int size);
|
|
|
|
|
2015-11-20 09:25:13 +00:00
|
|
|
Node* ProcessCallArguments(const Operator* call_op, Node* callee,
|
2015-11-17 12:18:25 +00:00
|
|
|
interpreter::Register receiver, size_t arity);
|
2016-02-15 08:18:16 +00:00
|
|
|
Node* ProcessCallNewArguments(const Operator* call_new_op, Node* callee,
|
|
|
|
Node* new_target,
|
2015-11-20 09:25:13 +00:00
|
|
|
interpreter::Register first_arg, size_t arity);
|
|
|
|
Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
|
|
|
|
interpreter::Register first_arg,
|
|
|
|
size_t arity);
|
2015-11-17 12:18:25 +00:00
|
|
|
|
2016-10-20 08:22:29 +00:00
|
|
|
// Prepare information for eager deoptimization. This information is carried
|
|
|
|
// by dedicated {Checkpoint} nodes that are wired into the effect chain.
|
|
|
|
// Conceptually this frame state is "before" a given operation.
|
|
|
|
void PrepareEagerCheckpoint();
|
|
|
|
|
|
|
|
// Prepare information for lazy deoptimization. This information is attached
|
|
|
|
// to the given node and the output value produced by the node is combined.
|
|
|
|
// Conceptually this frame state is "after" a given operation.
|
|
|
|
void PrepareFrameState(Node* node, OutputFrameStateCombine combine);
|
|
|
|
|
[runtime] Optimize and unify rest parameters.
Replace the somewhat awkward RestParamAccessStub, which would always
call into the runtime anyway with a proper FastNewRestParameterStub,
which is basically based on the code that was already there for strict
arguments object materialization. But for rest parameters we could
optimize even further (leading to 8-10x improvements for functions with
rest parameters), by fixing the internal formal parameter count:
Every SharedFunctionInfo has a formal_parameter_count field, which
specifies the number of formal parameters, and is used to decide whether
we need to create an arguments adaptor frame when calling a function
(i.e. if there's a mismatch between the actual and expected parameters).
Previously the formal_parameter_count included the rest parameter, which
was sort of unfortunate, as that meant that calling a function with only
the non-rest parameters still required an arguments adaptor (plus some
other oddities). Now with this CL we fix, so that we do no longer
include the rest parameter in that count. Thereby checking for rest
parameters is very efficient, as we only need to check whether there is
an arguments adaptor frame, and if not create an empty array, otherwise
check whether the arguments adaptor frame has more parameters than
specified by the formal_parameter_count.
The FastNewRestParameterStub is written in a way that it can be directly
used by Ignition as well, and with some tweaks to the TurboFan backends
and the CodeStubAssembler, we should be able to rewrite it as
TurboFanCodeStub in the near future.
Drive-by-fix: Refactor and unify the CreateArgumentsType which was
different in TurboFan and Ignition; now we have a single enum class
which is used in both TurboFan and Ignition.
R=jarin@chromium.org, rmcilroy@chromium.org
TBR=rossberg@chromium.org
BUG=v8:2159
LOG=n
Review URL: https://codereview.chromium.org/1676883002
Cr-Commit-Position: refs/heads/master@{#33809}
2016-02-08 10:08:21 +00:00
|
|
|
void BuildCreateArguments(CreateArgumentsType type);
|
2016-11-16 18:17:22 +00:00
|
|
|
Node* BuildLoadGlobal(Handle<Name> name, uint32_t feedback_slot_index,
|
|
|
|
TypeofMode typeof_mode);
|
2016-02-09 16:42:10 +00:00
|
|
|
void BuildStoreGlobal(LanguageMode language_mode);
|
|
|
|
void BuildNamedStore(LanguageMode language_mode);
|
|
|
|
void BuildKeyedStore(LanguageMode language_mode);
|
2016-01-29 10:15:26 +00:00
|
|
|
void BuildLdaLookupSlot(TypeofMode typeof_mode);
|
2016-09-16 13:26:44 +00:00
|
|
|
void BuildLdaLookupContextSlot(TypeofMode typeof_mode);
|
2016-09-20 10:31:24 +00:00
|
|
|
void BuildLdaLookupGlobalSlot(TypeofMode typeof_mode);
|
2016-01-29 10:15:26 +00:00
|
|
|
void BuildStaLookupSlot(LanguageMode language_mode);
|
2016-10-27 09:35:36 +00:00
|
|
|
void BuildCall(TailCallMode tail_call_mode,
|
|
|
|
ConvertReceiverMode receiver_hint);
|
2016-02-01 14:01:22 +00:00
|
|
|
void BuildThrow();
|
2016-01-29 10:15:26 +00:00
|
|
|
void BuildBinaryOp(const Operator* op);
|
2016-07-05 13:44:05 +00:00
|
|
|
void BuildBinaryOpWithImmediate(const Operator* op);
|
2016-01-29 10:15:26 +00:00
|
|
|
void BuildCompareOp(const Operator* op);
|
2016-02-09 16:42:10 +00:00
|
|
|
void BuildDelete(LanguageMode language_mode);
|
2016-07-29 11:14:55 +00:00
|
|
|
void BuildCastOperator(const Operator* op);
|
2016-01-29 10:15:26 +00:00
|
|
|
void BuildForInPrepare();
|
|
|
|
void BuildForInNext();
|
2016-03-22 11:35:09 +00:00
|
|
|
void BuildInvokeIntrinsic();
|
2015-11-17 12:18:25 +00:00
|
|
|
|
2016-09-29 16:08:26 +00:00
|
|
|
// Check the context chain for extensions, for lookup fast paths.
|
|
|
|
Environment* CheckContextExtensions(uint32_t depth);
|
|
|
|
|
2016-08-09 06:48:03 +00:00
|
|
|
// Helper function to create binary operation hint from the recorded
|
|
|
|
// type feedback.
|
2016-08-23 14:59:10 +00:00
|
|
|
BinaryOperationHint GetBinaryOperationHint(int operand_index);
|
2016-08-19 12:58:43 +00:00
|
|
|
|
2016-08-30 10:21:02 +00:00
|
|
|
// Helper function to create compare operation hint from the recorded
|
|
|
|
// type feedback.
|
|
|
|
CompareOperationHint GetCompareOperationHint();
|
|
|
|
|
2016-09-14 04:12:26 +00:00
|
|
|
// Helper function to compute call frequency from the recorded type
|
|
|
|
// feedback.
|
|
|
|
float ComputeCallFrequency(int slot_id) const;
|
|
|
|
|
2015-12-16 16:29:09 +00:00
|
|
|
// Control flow plumbing.
|
|
|
|
void BuildJump();
|
2016-09-05 08:43:17 +00:00
|
|
|
void BuildJumpIf(Node* condition);
|
|
|
|
void BuildJumpIfNot(Node* condition);
|
2016-01-05 19:08:11 +00:00
|
|
|
void BuildJumpIfEqual(Node* comperand);
|
2016-09-05 08:43:17 +00:00
|
|
|
void BuildJumpIfTrue();
|
|
|
|
void BuildJumpIfFalse();
|
|
|
|
void BuildJumpIfToBooleanTrue();
|
|
|
|
void BuildJumpIfToBooleanFalse();
|
2016-02-12 15:24:01 +00:00
|
|
|
void BuildJumpIfNotHole();
|
[ignition] desugar GetIterator() via bytecode rather than via AST
Introduces:
- a new AST node representing the GetIterator() algorithm in the specification, to be used by ForOfStatement, YieldExpression (in the case of delegating yield*), and the future `for-await-of` loop proposed in http://tc39.github.io/proposal-async-iteration/#sec-async-iterator-value-unwrap-functions.
- a new opcode (JumpIfJSReceiver), which is useful for `if Type(object) is not Object` checks which are common throughout the specification. This node is easily eliminated by TurboFan.
The AST node is desugared specially in bytecode, rather than manually when building the AST. The benefit of this is that desugaring in the BytecodeGenerator is much simpler and easier to understand than desugaring the AST.
This also reduces parse time very slightly, and allows us to use LoadIC rather than KeyedLoadIC, which seems to have better baseline performance. This results in a ~20% improvement in test/js-perf-test/Iterators micro-benchmarks, which I believe owes to the use of the slightly faster LoadIC as opposed to the KeyedLoadIC in the baseline case. Both produce identical optimized code via TurboFan when the type check can be eliminated, and the load can be replaced with a constant value.
BUG=v8:4280
R=bmeurer@chromium.org, rmcilroy@chromium.org, adamk@chromium.org, neis@chromium.org, jarin@chromium.org
TBR=rossberg@chromium.org
Review-Url: https://codereview.chromium.org/2557593004
Cr-Commit-Position: refs/heads/master@{#41555}
2016-12-07 15:19:52 +00:00
|
|
|
void BuildJumpIfJSReceiver();
|
2015-12-16 16:29:09 +00:00
|
|
|
|
2016-02-01 09:47:19 +00:00
|
|
|
// Simulates control flow by forward-propagating environments.
|
|
|
|
void MergeIntoSuccessorEnvironment(int target_offset);
|
|
|
|
void BuildLoopHeaderEnvironment(int current_offset);
|
|
|
|
void SwitchToMergeEnvironment(int current_offset);
|
2015-12-16 16:29:09 +00:00
|
|
|
|
2016-02-01 12:17:53 +00:00
|
|
|
// Simulates control flow that exits the function body.
|
|
|
|
void MergeControlToLeaveFunction(Node* exit);
|
|
|
|
|
2016-09-13 08:41:55 +00:00
|
|
|
// Builds entry points that are used by OSR deconstruction.
|
|
|
|
void BuildOSRLoopEntryPoint(int current_offset);
|
|
|
|
void BuildOSRNormalEntryPoint();
|
|
|
|
|
2016-08-08 10:01:09 +00:00
|
|
|
// Builds loop exit nodes for every exited loop between the current bytecode
|
|
|
|
// offset and {target_offset}.
|
|
|
|
void BuildLoopExitsForBranch(int target_offset);
|
|
|
|
void BuildLoopExitsForFunctionExit();
|
|
|
|
void BuildLoopExitsUntilLoop(int loop_offset);
|
|
|
|
|
2016-01-28 12:18:14 +00:00
|
|
|
// Simulates entry and exit of exception handlers.
|
|
|
|
void EnterAndExitExceptionHandlers(int current_offset);
|
|
|
|
|
2016-12-01 14:24:10 +00:00
|
|
|
// Update the current position of the {SourcePositionTable} to that of the
|
|
|
|
// bytecode at {offset}, if any.
|
|
|
|
void UpdateCurrentSourcePosition(SourcePositionTableIterator* it, int offset);
|
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
// Growth increment for the temporary buffer used to construct input lists to
|
|
|
|
// new nodes.
|
|
|
|
static const int kInputBufferSizeIncrement = 64;
|
|
|
|
|
2016-01-28 12:18:14 +00:00
|
|
|
// An abstract representation for an exception handler that is being
|
|
|
|
// entered and exited while the graph builder is iterating over the
|
|
|
|
// underlying bytecode. The exception handlers within the bytecode are
|
|
|
|
// well scoped, hence will form a stack during iteration.
|
|
|
|
struct ExceptionHandler {
|
2016-02-04 13:43:45 +00:00
|
|
|
int start_offset_; // Start offset of the handled area in the bytecode.
|
|
|
|
int end_offset_; // End offset of the handled area in the bytecode.
|
|
|
|
int handler_offset_; // Handler entry offset within the bytecode.
|
|
|
|
int context_register_; // Index of register holding handler context.
|
2016-01-28 12:18:14 +00:00
|
|
|
};
|
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
// Field accessors
|
2016-01-29 10:15:26 +00:00
|
|
|
Graph* graph() const { return jsgraph_->graph(); }
|
2015-09-10 16:21:34 +00:00
|
|
|
CommonOperatorBuilder* common() const { return jsgraph_->common(); }
|
|
|
|
Zone* graph_zone() const { return graph()->zone(); }
|
|
|
|
JSGraph* jsgraph() const { return jsgraph_; }
|
|
|
|
JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); }
|
[ignition] desugar GetIterator() via bytecode rather than via AST
Introduces:
- a new AST node representing the GetIterator() algorithm in the specification, to be used by ForOfStatement, YieldExpression (in the case of delegating yield*), and the future `for-await-of` loop proposed in http://tc39.github.io/proposal-async-iteration/#sec-async-iterator-value-unwrap-functions.
- a new opcode (JumpIfJSReceiver), which is useful for `if Type(object) is not Object` checks which are common throughout the specification. This node is easily eliminated by TurboFan.
The AST node is desugared specially in bytecode, rather than manually when building the AST. The benefit of this is that desugaring in the BytecodeGenerator is much simpler and easier to understand than desugaring the AST.
This also reduces parse time very slightly, and allows us to use LoadIC rather than KeyedLoadIC, which seems to have better baseline performance. This results in a ~20% improvement in test/js-perf-test/Iterators micro-benchmarks, which I believe owes to the use of the slightly faster LoadIC as opposed to the KeyedLoadIC in the baseline case. Both produce identical optimized code via TurboFan when the type check can be eliminated, and the load can be replaced with a constant value.
BUG=v8:4280
R=bmeurer@chromium.org, rmcilroy@chromium.org, adamk@chromium.org, neis@chromium.org, jarin@chromium.org
TBR=rossberg@chromium.org
Review-Url: https://codereview.chromium.org/2557593004
Cr-Commit-Position: refs/heads/master@{#41555}
2016-12-07 15:19:52 +00:00
|
|
|
SimplifiedOperatorBuilder* simplified() const {
|
|
|
|
return jsgraph_->simplified();
|
|
|
|
}
|
2015-09-10 16:21:34 +00:00
|
|
|
Zone* local_zone() const { return local_zone_; }
|
|
|
|
const Handle<BytecodeArray>& bytecode_array() const {
|
|
|
|
return bytecode_array_;
|
|
|
|
}
|
2016-01-28 12:18:14 +00:00
|
|
|
const Handle<HandlerTable>& exception_handler_table() const {
|
|
|
|
return exception_handler_table_;
|
|
|
|
}
|
2016-02-17 14:10:17 +00:00
|
|
|
const Handle<TypeFeedbackVector>& feedback_vector() const {
|
|
|
|
return feedback_vector_;
|
|
|
|
}
|
2015-12-18 08:41:10 +00:00
|
|
|
const FrameStateFunctionInfo* frame_state_function_info() const {
|
|
|
|
return frame_state_function_info_;
|
|
|
|
}
|
2015-09-10 16:21:34 +00:00
|
|
|
|
2016-01-29 10:15:26 +00:00
|
|
|
const interpreter::BytecodeArrayIterator& bytecode_iterator() const {
|
|
|
|
return *bytecode_iterator_;
|
2015-12-16 16:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_bytecode_iterator(
|
|
|
|
const interpreter::BytecodeArrayIterator* bytecode_iterator) {
|
|
|
|
bytecode_iterator_ = bytecode_iterator;
|
|
|
|
}
|
|
|
|
|
2016-11-22 18:05:03 +00:00
|
|
|
const BytecodeAnalysis* bytecode_analysis() const {
|
|
|
|
return bytecode_analysis_;
|
2015-12-16 16:29:09 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 18:05:03 +00:00
|
|
|
void set_bytecode_analysis(const BytecodeAnalysis* bytecode_analysis) {
|
|
|
|
bytecode_analysis_ = bytecode_analysis;
|
2016-08-08 10:01:09 +00:00
|
|
|
}
|
|
|
|
|
2016-09-07 13:00:04 +00:00
|
|
|
bool IsLivenessAnalysisEnabled() const {
|
|
|
|
return this->is_liveness_analysis_enabled_;
|
|
|
|
}
|
|
|
|
|
2016-01-29 10:15:26 +00:00
|
|
|
#define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name();
|
2015-09-10 16:21:34 +00:00
|
|
|
BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
|
|
|
|
#undef DECLARE_VISIT_BYTECODE
|
|
|
|
|
|
|
|
Zone* local_zone_;
|
|
|
|
JSGraph* jsgraph_;
|
2016-09-14 10:20:08 +00:00
|
|
|
float const invocation_frequency_;
|
2015-09-10 16:21:34 +00:00
|
|
|
Handle<BytecodeArray> bytecode_array_;
|
2016-01-28 12:18:14 +00:00
|
|
|
Handle<HandlerTable> exception_handler_table_;
|
2016-02-17 14:10:17 +00:00
|
|
|
Handle<TypeFeedbackVector> feedback_vector_;
|
2015-12-18 08:41:10 +00:00
|
|
|
const FrameStateFunctionInfo* frame_state_function_info_;
|
2015-12-16 16:29:09 +00:00
|
|
|
const interpreter::BytecodeArrayIterator* bytecode_iterator_;
|
2016-11-22 18:05:03 +00:00
|
|
|
const BytecodeAnalysis* bytecode_analysis_;
|
2015-09-10 16:21:34 +00:00
|
|
|
Environment* environment_;
|
2016-07-27 08:19:43 +00:00
|
|
|
BailoutId osr_ast_id_;
|
2016-12-01 14:24:10 +00:00
|
|
|
int osr_loop_offset_;
|
2015-09-10 16:21:34 +00:00
|
|
|
|
2016-02-01 09:47:19 +00:00
|
|
|
// Merge environments are snapshots of the environment at points where the
|
|
|
|
// control flow merges. This models a forward data flow propagation of all
|
|
|
|
// values from all predecessors of the merge in question.
|
2015-12-16 16:29:09 +00:00
|
|
|
ZoneMap<int, Environment*> merge_environments_;
|
|
|
|
|
2016-01-28 12:18:14 +00:00
|
|
|
// Exception handlers currently entered by the iteration.
|
|
|
|
ZoneStack<ExceptionHandler> exception_handlers_;
|
|
|
|
int current_exception_handler_;
|
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
// Temporary storage for building node input lists.
|
|
|
|
int input_buffer_size_;
|
|
|
|
Node** input_buffer_;
|
|
|
|
|
|
|
|
// Nodes representing values in the activation record.
|
|
|
|
SetOncePointer<Node> function_context_;
|
2015-11-17 09:05:37 +00:00
|
|
|
SetOncePointer<Node> function_closure_;
|
2015-12-01 17:28:43 +00:00
|
|
|
SetOncePointer<Node> new_target_;
|
2015-11-17 09:05:37 +00:00
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
// Control nodes that exit the function body.
|
|
|
|
ZoneVector<Node*> exit_controls_;
|
|
|
|
|
2016-09-07 13:00:04 +00:00
|
|
|
bool const is_liveness_analysis_enabled_;
|
|
|
|
|
|
|
|
StateValuesCache state_values_cache_;
|
|
|
|
|
2016-12-01 14:24:10 +00:00
|
|
|
// The source position table, to be populated.
|
2016-10-13 13:13:59 +00:00
|
|
|
SourcePositionTable* source_positions_;
|
|
|
|
|
This CL enables precise source positions for all V8 compilers. It merges compiler::SourcePosition and internal::SourcePosition to a single class used throughout the codebase. The new internal::SourcePosition instances store an id identifying an inlined function in addition to a script offset.
SourcePosition::InliningId() refers to a the new table DeoptimizationInputData::InliningPositions(), which provides the following data for every inlining id:
- The inlined SharedFunctionInfo as an offset into DeoptimizationInfo::LiteralArray
- The SourcePosition of the inlining. Recursively, this yields the full inlining stack.
Before the Code object is created, the same information can be found in CompilationInfo::inlined_functions().
If SourcePosition::InliningId() is SourcePosition::kNotInlined, it refers to the outer (non-inlined) function.
So every SourcePosition has full information about its inlining stack, as long as the corresponding Code object is known. The internal represenation of a source position is a positive 64bit integer.
All compilers create now appropriate source positions for inlined functions. In the case of Turbofan, this required using AstGraphBuilderWithPositions for inlined functions too. So this class is now moved to a header file.
At the moment, the additional information in source positions is only used in --trace-deopt and --code-comments. The profiler needs to be updated, at the moment it gets the correct script offsets from the deopt info, but the wrong script id from the reconstructed deopt stack, which can lead to wrong outputs. This should be resolved by making the profiler use the new inlining information for deopts.
I activated the inlined deoptimization tests in test-cpu-profiler.cc for Turbofan, changing them to a case where the deopt stack and the inlining position agree. It is currently still broken for other cases.
The following additional changes were necessary:
- The source position table (internal::SourcePositionTableBuilder etc.) supports now 64bit source positions. Encoding source positions in a single 64bit int together with the difference encoding in the source position table results in very little overhead for the inlining id, since only 12% of the source positions in Octane have a changed inlining id.
- The class HPositionInfo was effectively dead code and is now removed.
- SourcePosition has new printing and information facilities, including computing a full inlining stack.
- I had to rename compiler/source-position.{h,cc} to compiler/compiler-source-position-table.{h,cc} to avoid clashes with the new src/source-position.cc file.
- I wrote the new wrapper PodArray for ByteArray. It is a template working with any POD-type. This is used in DeoptimizationInputData::InliningPositions().
- I removed HInlinedFunctionInfo and HGraph::inlined_function_infos, because they were only used for the now obsolete Crankshaft inlining ids.
- Crankshaft managed a list of inlined functions in Lithium: LChunk::inlined_functions. This is an analog structure to CompilationInfo::inlined_functions. So I removed LChunk::inlined_functions and made Crankshaft use CompilationInfo::inlined_functions instead, because this was necessary to register the offsets into the literal array in a uniform way. This is a safe change because LChunk::inlined_functions has no other uses and the functions in CompilationInfo::inlined_functions have a strictly longer lifespan, being created earlier (in Hydrogen already).
BUG=v8:5432
Review-Url: https://codereview.chromium.org/2451853002
Cr-Commit-Position: refs/heads/master@{#40975}
2016-11-14 17:21:37 +00:00
|
|
|
SourcePosition const start_position_;
|
|
|
|
|
2016-08-23 14:59:10 +00:00
|
|
|
static int const kBinaryOperationHintIndex = 1;
|
|
|
|
static int const kCountOperationHintIndex = 0;
|
|
|
|
static int const kBinaryOperationSmiHintIndex = 2;
|
|
|
|
|
2015-09-10 16:21:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilder);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
|