Commit 9d23ec9f authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[turbofan] Remove deoptimization support from AstGraphBuilder.

The AST-based graph builder is by now only used for asm.js code. This
change hard-codes this assumption into the compilation pipeline and
hence allows us to remove support pertaining to deoptimization from
optimized code that was not derived from bytecode.

R=jarin@chromium.org
BUG=v8:6409

Change-Id: I1138f16f663db5b9ee34e3110184067b8fcffc8b
Reviewed-on: https://chromium-review.googlesource.com/531026
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45887}
parent f14d1b62
......@@ -1351,8 +1351,6 @@ v8_source_set("v8_base") {
"src/compiler/linkage.h",
"src/compiler/live-range-separator.cc",
"src/compiler/live-range-separator.h",
"src/compiler/liveness-analyzer.cc",
"src/compiler/liveness-analyzer.h",
"src/compiler/load-elimination.cc",
"src/compiler/load-elimination.h",
"src/compiler/loop-analysis.cc",
......
This diff is collapsed.
......@@ -8,7 +8,6 @@
#include "src/ast/ast.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/liveness-analyzer.h"
#include "src/compiler/state-values-utils.h"
namespace v8 {
......@@ -114,9 +113,6 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
// Cache for StateValues nodes for frame states.
StateValuesCache state_values_cache_;
// Analyzer of local variable liveness.
LivenessAnalyzer liveness_analyzer_;
// Function info for frame state construction.
const FrameStateFunctionInfo* const frame_state_function_info_;
......@@ -140,7 +136,6 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
ZoneVector<Handle<Object>>* globals() { return &globals_; }
Scope* current_scope() const;
Node* current_context() const;
LivenessAnalyzer* liveness_analyzer() { return &liveness_analyzer_; }
const FrameStateFunctionInfo* frame_state_function_info() const {
return frame_state_function_info_;
}
......@@ -239,10 +234,6 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
// If so, record the stack height into the compilation and return {true}.
bool CheckOsrEntry(IterationStatement* stmt);
// Computes local variable liveness and replaces dead variables in
// frame states with the undefined values.
void ClearNonLiveSlotsInFrameStates();
Node** EnsureInputBufferSize(int size);
// Named and keyed loads require a VectorSlotPair for successful lowering.
......@@ -426,7 +417,6 @@ class AstGraphBuilder::Environment : public ZoneObject {
// Operations on parameter or local variables.
void Bind(Variable* variable, Node* node);
Node* Lookup(Variable* variable);
void MarkAllLocalsLive();
// Raw operations on parameter variables.
void RawParameterBind(int index, Node* node);
......@@ -501,7 +491,6 @@ class AstGraphBuilder::Environment : public ZoneObject {
// Mark this environment as being unreachable.
void MarkAsUnreachable() {
UpdateControlDependency(builder()->jsgraph()->Dead());
liveness_block_ = nullptr;
}
bool IsMarkedAsUnreachable() {
return GetControlDependency()->opcode() == IrOpcode::kDead;
......@@ -528,7 +517,6 @@ class AstGraphBuilder::Environment : public ZoneObject {
AstGraphBuilder* builder_;
int parameters_count_;
int locals_count_;
LivenessAnalyzerBlock* liveness_block_;
NodeVector values_;
NodeVector contexts_;
Node* control_dependency_;
......@@ -537,19 +525,14 @@ class AstGraphBuilder::Environment : public ZoneObject {
Node* locals_node_;
Node* stack_node_;
explicit Environment(Environment* copy,
LivenessAnalyzerBlock* liveness_block);
explicit Environment(Environment* copy);
Environment* CopyAndShareLiveness();
void UpdateStateValues(Node** state_values, int offset, int count);
Zone* zone() const { return builder_->local_zone(); }
Graph* graph() const { return builder_->graph(); }
AstGraphBuilder* builder() const { return builder_; }
CommonOperatorBuilder* common() { return builder_->common(); }
NodeVector* values() { return &values_; }
NodeVector* contexts() { return &contexts_; }
LivenessAnalyzerBlock* liveness_block() { return liveness_block_; }
bool IsLivenessAnalysisEnabled();
bool IsLivenessBlockConsistent();
// Prepare environment to be used as loop header.
void PrepareForLoop(BitVector* assigned);
......
......@@ -8,7 +8,6 @@
#include "src/compiler/bytecode-analysis.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-type-hint-lowering.h"
#include "src/compiler/liveness-analyzer.h"
#include "src/compiler/state-values-utils.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/bytecode-flags.h"
......
// Copyright 2014 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/base/adapters.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/liveness-analyzer.h"
#include "src/compiler/node.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/state-values-utils.h"
namespace v8 {
namespace internal {
namespace compiler {
LivenessAnalyzer::LivenessAnalyzer(size_t local_count, bool has_accumulator,
Zone* zone)
: zone_(zone),
blocks_(zone),
local_count_(local_count),
has_accumulator_(has_accumulator),
queue_(zone) {}
void LivenessAnalyzer::Print(std::ostream& os) {
for (auto block : blocks_) {
block->Print(os);
os << std::endl;
}
}
LivenessAnalyzerBlock* LivenessAnalyzer::NewBlock() {
LivenessAnalyzerBlock* result =
new (zone()->New(sizeof(LivenessAnalyzerBlock))) LivenessAnalyzerBlock(
blocks_.size(), local_count_, has_accumulator_, zone());
blocks_.push_back(result);
return result;
}
LivenessAnalyzerBlock* LivenessAnalyzer::NewBlock(
LivenessAnalyzerBlock* predecessor) {
LivenessAnalyzerBlock* result = NewBlock();
result->AddPredecessor(predecessor);
return result;
}
void LivenessAnalyzer::Queue(LivenessAnalyzerBlock* block) {
if (!block->IsQueued()) {
block->SetQueued();
queue_.push(block);
}
}
void LivenessAnalyzer::Run(NonLiveFrameStateSlotReplacer* replacer) {
if (local_count_ == 0 && !has_accumulator_) {
// No variables => nothing to do.
return;
}
// Put all blocks into the queue.
DCHECK(queue_.empty());
for (auto block : blocks_) {
Queue(block);
}
// Compute the fix-point.
BitVector working_area(
static_cast<int>(local_count_) + (has_accumulator_ ? 1 : 0), zone_);
while (!queue_.empty()) {
LivenessAnalyzerBlock* block = queue_.front();
queue_.pop();
block->Process(&working_area, nullptr);
for (auto i = block->pred_begin(); i != block->pred_end(); i++) {
if ((*i)->UpdateLive(&working_area)) {
Queue(*i);
}
}
}
// Update the frame states according to the liveness.
for (auto block : blocks_) {
block->Process(&working_area, replacer);
}
}
LivenessAnalyzerBlock::LivenessAnalyzerBlock(size_t id, size_t local_count,
bool has_accumulator, Zone* zone)
: entries_(zone),
predecessors_(zone),
live_(static_cast<int>(local_count) + (has_accumulator ? 1 : 0), zone),
queued_(false),
has_accumulator_(has_accumulator),
id_(id) {}
void LivenessAnalyzerBlock::Process(BitVector* result,
NonLiveFrameStateSlotReplacer* replacer) {
queued_ = false;
// Copy the bitvector to the target bit vector.
result->CopyFrom(live_);
for (auto entry : base::Reversed(entries_)) {
switch (entry.kind()) {
case Entry::kLookup:
result->Add(entry.var());
break;
case Entry::kBind:
result->Remove(entry.var());
break;
case Entry::kCheckpoint:
if (replacer != nullptr) {
replacer->ClearNonLiveFrameStateSlots(entry.node(), result);
}
break;
}
}
}
bool LivenessAnalyzerBlock::UpdateLive(BitVector* working_area) {
return live_.UnionIsChanged(*working_area);
}
void NonLiveFrameStateSlotReplacer::ClearNonLiveFrameStateSlots(
Node* frame_state, BitVector* liveness) {
DCHECK_EQ(liveness->length(), permanently_live_.length());
DCHECK_EQ(frame_state->opcode(), IrOpcode::kFrameState);
Node* locals_state = frame_state->InputAt(1);
DCHECK_EQ(locals_state->opcode(), IrOpcode::kStateValues);
int count = liveness->length() - (has_accumulator_ ? 1 : 0);
DCHECK_EQ(count, static_cast<int>(StateValuesAccess(locals_state).size()));
for (int i = 0; i < count; i++) {
if (!liveness->Contains(i) && !permanently_live_.Contains(i)) {
Node* new_values = ClearNonLiveStateValues(locals_state, liveness);
frame_state->ReplaceInput(1, new_values);
break;
}
}
if (has_accumulator_) {
DCHECK_EQ(frame_state->InputAt(2)->opcode(), IrOpcode::kStateValues);
DCHECK_EQ(
static_cast<int>(StateValuesAccess(frame_state->InputAt(2)).size()), 1);
int index = liveness->length() - 1;
if (!liveness->Contains(index) && !permanently_live_.Contains(index)) {
Node* new_value =
state_values_cache()->GetNodeForValues(&replacement_node_, 1);
frame_state->ReplaceInput(2, new_value);
}
}
}
Node* NonLiveFrameStateSlotReplacer::ClearNonLiveStateValues(
Node* values, BitVector* liveness) {
DCHECK(inputs_buffer_.empty());
int var = 0;
for (Node* value_node : values->inputs()) {
// Make sure this isn't a state value tree
DCHECK(value_node->opcode() != IrOpcode::kStateValues);
// Index of the next variable is its furure index in the inputs buffer,
// i.e., the buffer's size.
bool live = liveness->Contains(var) || permanently_live_.Contains(var);
inputs_buffer_.push_back(live ? value_node : replacement_node_);
var++;
}
Node* result = state_values_cache()->GetNodeForValues(
inputs_buffer_.empty() ? nullptr : &(inputs_buffer_.front()),
inputs_buffer_.size());
inputs_buffer_.clear();
return result;
}
void LivenessAnalyzerBlock::Print(std::ostream& os) {
os << "Block " << id();
bool first = true;
for (LivenessAnalyzerBlock* pred : predecessors_) {
if (!first) {
os << ", ";
} else {
os << "; predecessors: ";
first = false;
}
os << pred->id();
}
os << std::endl;
for (auto entry : entries_) {
os << " ";
switch (entry.kind()) {
case Entry::kLookup:
if (has_accumulator_ && entry.var() == live_.length() - 1) {
os << "- Lookup accumulator" << std::endl;
} else {
os << "- Lookup " << entry.var() << std::endl;
}
break;
case Entry::kBind:
if (has_accumulator_ && entry.var() == live_.length() - 1) {
os << "- Bind accumulator" << std::endl;
} else {
os << "- Bind " << entry.var() << std::endl;
}
break;
case Entry::kCheckpoint:
os << "- Checkpoint " << entry.node()->id() << std::endl;
break;
}
}
if (live_.length() > 0) {
os << " Live set: ";
for (int i = 0; i < live_.length(); i++) {
os << (live_.Contains(i) ? "L" : ".");
}
os << std::endl;
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
// 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_LIVENESS_ANAYZER_H_
#define V8_COMPILER_LIVENESS_ANAYZER_H_
#include "src/bit-vector.h"
#include "src/compiler/node.h"
#include "src/globals.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
namespace compiler {
class LivenessAnalyzerBlock;
class Node;
class StateValuesCache;
class NonLiveFrameStateSlotReplacer {
public:
void ClearNonLiveFrameStateSlots(Node* frame_state, BitVector* liveness);
NonLiveFrameStateSlotReplacer(StateValuesCache* state_values_cache,
Node* replacement, size_t local_count,
bool has_accumulator, Zone* local_zone)
: replacement_node_(replacement),
state_values_cache_(state_values_cache),
local_zone_(local_zone),
permanently_live_(
static_cast<int>(local_count) + (has_accumulator ? 1 : 0),
local_zone),
inputs_buffer_(local_zone),
has_accumulator_(has_accumulator) {}
// TODO(leszeks): Not used by bytecode, remove once AST graph builder is gone.
void MarkPermanentlyLive(int var) { permanently_live_.Add(var); }
private:
Node* ClearNonLiveStateValues(Node* frame_state, BitVector* liveness);
StateValuesCache* state_values_cache() { return state_values_cache_; }
Zone* local_zone() { return local_zone_; }
// Node that replaces dead values.
Node* replacement_node_;
// Reference to state values cache so that we can create state values
// nodes.
StateValuesCache* state_values_cache_;
Zone* local_zone_;
BitVector permanently_live_;
NodeVector inputs_buffer_;
bool has_accumulator_;
};
class V8_EXPORT_PRIVATE LivenessAnalyzer {
public:
LivenessAnalyzer(size_t local_count, bool has_accumulator, Zone* zone);
LivenessAnalyzerBlock* NewBlock();
LivenessAnalyzerBlock* NewBlock(LivenessAnalyzerBlock* predecessor);
void Run(NonLiveFrameStateSlotReplacer* relaxer);
Zone* zone() { return zone_; }
void Print(std::ostream& os);
size_t local_count() { return local_count_; }
private:
void Queue(LivenessAnalyzerBlock* block);
Zone* zone_;
ZoneDeque<LivenessAnalyzerBlock*> blocks_;
size_t local_count_;
// TODO(leszeks): Always true for bytecode, remove once AST graph builder is
// gone.
bool has_accumulator_;
ZoneQueue<LivenessAnalyzerBlock*> queue_;
};
class LivenessAnalyzerBlock {
public:
friend class LivenessAnalyzer;
void Lookup(int var) { entries_.push_back(Entry(Entry::kLookup, var)); }
void Bind(int var) { entries_.push_back(Entry(Entry::kBind, var)); }
void LookupAccumulator() {
DCHECK(has_accumulator_);
// The last entry is the accumulator entry.
entries_.push_back(Entry(Entry::kLookup, live_.length() - 1));
}
void BindAccumulator() {
DCHECK(has_accumulator_);
// The last entry is the accumulator entry.
entries_.push_back(Entry(Entry::kBind, live_.length() - 1));
}
void Checkpoint(Node* node) { entries_.push_back(Entry(node)); }
void AddPredecessor(LivenessAnalyzerBlock* b) { predecessors_.push_back(b); }
LivenessAnalyzerBlock* GetPredecessor() {
DCHECK(predecessors_.size() == 1);
return predecessors_[0];
}
private:
class Entry {
public:
enum Kind { kBind, kLookup, kCheckpoint };
Kind kind() const { return kind_; }
Node* node() const {
DCHECK(kind() == kCheckpoint);
return node_;
}
int var() const {
DCHECK(kind() != kCheckpoint);
return var_;
}
explicit Entry(Node* node) : kind_(kCheckpoint), var_(-1), node_(node) {}
Entry(Kind kind, int var) : kind_(kind), var_(var), node_(nullptr) {
DCHECK(kind != kCheckpoint);
}
private:
Kind kind_;
int var_;
Node* node_;
};
LivenessAnalyzerBlock(size_t id, size_t local_count, bool has_accumulator,
Zone* zone);
void Process(BitVector* result, NonLiveFrameStateSlotReplacer* relaxer);
bool UpdateLive(BitVector* working_area);
void SetQueued() { queued_ = true; }
bool IsQueued() { return queued_; }
ZoneDeque<LivenessAnalyzerBlock*>::const_iterator pred_begin() {
return predecessors_.begin();
}
ZoneDeque<LivenessAnalyzerBlock*>::const_iterator pred_end() {
return predecessors_.end();
}
size_t id() { return id_; }
void Print(std::ostream& os);
ZoneDeque<Entry> entries_;
ZoneDeque<LivenessAnalyzerBlock*> predecessors_;
BitVector live_;
bool queued_;
bool has_accumulator_;
size_t id_;
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_AST_GRAPH_BUILDER_H_
......@@ -602,8 +602,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() {
info()->MarkAsLoopPeelingEnabled();
}
}
if (info()->is_optimizing_from_bytecode() ||
!info()->shared_info()->asm_function()) {
if (info()->is_optimizing_from_bytecode()) {
info()->MarkAsDeoptimizationEnabled();
if (FLAG_inline_accessors) {
info()->MarkAsAccessorInliningEnabled();
......@@ -773,7 +772,7 @@ struct GraphBuilderPhase {
void Run(PipelineData* data, Zone* temp_zone) {
if (data->info()->is_optimizing_from_bytecode()) {
// Bytecode graph builder assumes deoptimziation is enabled.
// Bytecode graph builder assumes deoptimization is enabled.
DCHECK(data->info()->is_deoptimization_enabled());
JSTypeHintLowering::Flags flags = JSTypeHintLowering::kNoFlags;
if (data->info()->is_bailout_on_uninitialized()) {
......@@ -786,6 +785,8 @@ struct GraphBuilderPhase {
data->source_positions(), SourcePosition::kNotInlined, flags);
graph_builder.CreateGraph();
} else {
// AST-based graph builder assumes deoptimization is disabled.
DCHECK(!data->info()->is_deoptimization_enabled());
AstGraphBuilderWithPositions graph_builder(
temp_zone, data->info(), data->jsgraph(), CallFrequency(1.0f),
data->loop_assignment(), data->source_positions());
......
......@@ -797,8 +797,6 @@
'compiler/jump-threading.h',
'compiler/linkage.cc',
'compiler/linkage.h',
'compiler/liveness-analyzer.cc',
'compiler/liveness-analyzer.h',
'compiler/live-range-separator.cc',
'compiler/live-range-separator.h',
'compiler/load-elimination.cc',
......
......@@ -169,13 +169,13 @@ Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) {
function);
info.SetOptimizing();
info.MarkAsDeoptimizationEnabled();
if (flags_ & CompilationInfo::kInliningEnabled) {
info.MarkAsInliningEnabled();
}
CHECK(Compiler::Compile(function, Compiler::CLEAR_EXCEPTION));
if (info.shared_info()->HasBytecodeArray()) {
info.MarkAsDeoptimizationEnabled();
info.MarkAsOptimizeFromBytecode();
} else {
CHECK(Compiler::ParseAndAnalyze(&info));
......
......@@ -29,6 +29,7 @@ static void InstallIsOptimizedHelper(v8::Isolate* isolate) {
TEST(DeoptSimple) {
FLAG_ignition = true;
FLAG_allow_natives_syntax = true;
FunctionTester T(
......@@ -46,6 +47,7 @@ TEST(DeoptSimple) {
TEST(DeoptSimpleInExpr) {
FLAG_ignition = true;
FLAG_allow_natives_syntax = true;
FunctionTester T(
......@@ -64,6 +66,7 @@ TEST(DeoptSimpleInExpr) {
TEST(DeoptExceptionHandlerCatch) {
FLAG_ignition = true;
FLAG_allow_natives_syntax = true;
FunctionTester T(
......@@ -83,6 +86,7 @@ TEST(DeoptExceptionHandlerCatch) {
TEST(DeoptExceptionHandlerFinally) {
FLAG_ignition = true;
FLAG_allow_natives_syntax = true;
FunctionTester T(
......@@ -102,6 +106,7 @@ TEST(DeoptExceptionHandlerFinally) {
TEST(DeoptTrivial) {
FLAG_ignition = true;
FLAG_allow_natives_syntax = true;
FunctionTester T(
......
......@@ -10,6 +10,7 @@ namespace internal {
namespace compiler {
TEST(Throw) {
FLAG_ignition = true;
FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})");
T.CheckThrows(T.true_value(), T.NewObject("new Error"));
......@@ -18,6 +19,7 @@ TEST(Throw) {
TEST(ThrowMessagePosition) {
FLAG_ignition = true;
static const char* src =
"(function(a, b) { \n"
" if (a == 1) throw 1; \n"
......@@ -44,6 +46,7 @@ TEST(ThrowMessagePosition) {
TEST(ThrowMessageDirectly) {
FLAG_ignition = true;
static const char* src =
"(function(a, b) {"
" if (a) { throw b; } else { throw new Error(b); }"
......@@ -62,6 +65,7 @@ TEST(ThrowMessageDirectly) {
TEST(ThrowMessageIndirectly) {
FLAG_ignition = true;
static const char* src =
"(function(a, b) {"
" try {"
......@@ -84,6 +88,7 @@ TEST(ThrowMessageIndirectly) {
TEST(Catch) {
FLAG_ignition = true;
const char* src =
"(function(a,b) {"
" var r = '-';"
......@@ -102,6 +107,7 @@ TEST(Catch) {
TEST(CatchNested) {
FLAG_ignition = true;
const char* src =
"(function(a,b) {"
" var r = '-';"
......@@ -125,6 +131,7 @@ TEST(CatchNested) {
TEST(CatchBreak) {
FLAG_ignition = true;
const char* src =
"(function(a,b) {"
" var r = '-';"
......@@ -149,6 +156,7 @@ TEST(CatchBreak) {
TEST(CatchCall) {
FLAG_ignition = true;
const char* src =
"(function(fun) {"
" var r = '-';"
......@@ -170,6 +178,7 @@ TEST(CatchCall) {
TEST(Finally) {
FLAG_ignition = true;
const char* src =
"(function(a,b) {"
" var r = '-';"
......@@ -187,6 +196,7 @@ TEST(Finally) {
TEST(FinallyBreak) {
FLAG_ignition = true;
const char* src =
"(function(a,b) {"
" var r = '-';"
......@@ -210,6 +220,7 @@ TEST(FinallyBreak) {
TEST(DeoptTry) {
FLAG_ignition = true;
const char* src =
"(function f(a) {"
" try {"
......@@ -226,6 +237,7 @@ TEST(DeoptTry) {
TEST(DeoptCatch) {
FLAG_ignition = true;
const char* src =
"(function f(a) {"
" try {"
......@@ -242,6 +254,7 @@ TEST(DeoptCatch) {
TEST(DeoptFinallyReturn) {
FLAG_ignition = true;
const char* src =
"(function f(a) {"
" try {"
......@@ -258,6 +271,7 @@ TEST(DeoptFinallyReturn) {
TEST(DeoptFinallyReThrow) {
FLAG_ignition = true;
const char* src =
"(function f(a) {"
" try {"
......
......@@ -387,6 +387,7 @@ TEST(PropertyKeyedDelete) {
TEST(GlobalLoad) {
FLAG_ignition = true;
FunctionTester T("(function() { return g; })");
T.CheckThrows(T.undefined(), T.undefined());
......@@ -396,6 +397,7 @@ TEST(GlobalLoad) {
TEST(GlobalStoreStrict) {
FLAG_ignition = true;
FunctionTester T("(function(a,b) { 'use strict'; g = a + b; return g; })");
T.CheckThrows(T.Val(22), T.Val(11));
......
......@@ -10,6 +10,7 @@ namespace internal {
namespace compiler {
TEST(TerminateAtMethodEntry) {
FLAG_ignition = true;
FunctionTester T("(function(a,b) { return 23; })");
T.CheckCall(T.Val(23));
......
......@@ -66,30 +66,35 @@ static void RunVariableTests(const char* source, const char* tests[]) {
TEST(StackLoadVariables) {
FLAG_ignition = true;
const char* source = "(function(a,r) { %s; return r; })";
RunVariableTests(source, load_tests);
}
TEST(ContextLoadVariables) {
FLAG_ignition = true;
const char* source = "(function(a,r) { %s; function f() {x} return r; })";
RunVariableTests(source, load_tests);
}
TEST(StackStoreVariables) {
FLAG_ignition = true;
const char* source = "(function(a,r) { %s; return r; })";
RunVariableTests(source, store_tests);
}
TEST(ContextStoreVariables) {
FLAG_ignition = true;
const char* source = "(function(a,r) { %s; function f() {x} return r; })";
RunVariableTests(source, store_tests);
}
TEST(SelfReferenceVariable) {
FLAG_ignition = true;
FunctionTester T("(function self() { return self; })");
T.CheckCall(T.function);
......
......@@ -72,7 +72,6 @@ v8_executable("unittests") {
"compiler/js-typed-lowering-unittest.cc",
"compiler/linkage-tail-call-unittest.cc",
"compiler/live-range-builder.h",
"compiler/liveness-analyzer-unittest.cc",
"compiler/load-elimination-unittest.cc",
"compiler/loop-peeling-unittest.cc",
"compiler/machine-operator-reducer-unittest.cc",
......
This diff is collapsed.
......@@ -64,7 +64,6 @@
'compiler/js-operator-unittest.cc',
'compiler/js-typed-lowering-unittest.cc',
'compiler/linkage-tail-call-unittest.cc',
'compiler/liveness-analyzer-unittest.cc',
'compiler/live-range-builder.h',
'compiler/regalloc/live-range-unittest.cc',
'compiler/load-elimination-unittest.cc',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment