mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 05:21:28 +00:00
Automatically assign temporary indices to definitions in the IL.
When added to the graph, automatically assign a temporary index (== stack height) to definitions. R=srdjan@google.com BUG= TEST= Review URL: https://chromiumcodereview.appspot.com//10316005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@7269 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
509a727216
commit
bf52684184
|
@ -48,11 +48,16 @@ void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
|
|||
exit()->SetSuccessor(other_fragment.entry());
|
||||
exit_ = other_fragment.exit();
|
||||
}
|
||||
temp_index_ = other_fragment.temp_index();
|
||||
}
|
||||
|
||||
|
||||
void EffectGraphVisitor::AddInstruction(Instruction* instruction) {
|
||||
ASSERT(is_open());
|
||||
DeallocateTempIndex(instruction->InputCount());
|
||||
if (instruction->IsDefinition()) {
|
||||
instruction->AsDefinition()->set_temp_index(AllocateTempIndex());
|
||||
}
|
||||
if (is_empty()) {
|
||||
entry_ = exit_ = instruction;
|
||||
} else {
|
||||
|
@ -91,12 +96,16 @@ void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment,
|
|||
// 3. Add a join or select one (or neither) of the arms as exit.
|
||||
if (true_exit == NULL) {
|
||||
exit_ = false_exit; // May be NULL.
|
||||
if (false_exit != NULL) temp_index_ = false_fragment.temp_index();
|
||||
} else if (false_exit == NULL) {
|
||||
exit_ = true_exit;
|
||||
temp_index_ = true_fragment.temp_index();
|
||||
} else {
|
||||
exit_ = new JoinEntryInstr();
|
||||
true_exit->SetSuccessor(exit_);
|
||||
false_exit->SetSuccessor(exit_);
|
||||
ASSERT(true_fragment.temp_index() == false_fragment.temp_index());
|
||||
temp_index_ = true_fragment.temp_index();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,7 +145,7 @@ void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment,
|
|||
|
||||
// Stores current context into the 'variable'
|
||||
void EffectGraphVisitor::BuildStoreContext(const LocalVariable& variable) {
|
||||
BindInstr* context = new BindInstr(temp_index(), new CurrentContextComp());
|
||||
BindInstr* context = new BindInstr(new CurrentContextComp());
|
||||
AddInstruction(context);
|
||||
StoreLocalComp* store_context =
|
||||
new StoreLocalComp(variable, new UseVal(context),
|
||||
|
@ -148,8 +157,7 @@ void EffectGraphVisitor::BuildStoreContext(const LocalVariable& variable) {
|
|||
// Loads context saved in 'context_variable' into the current context.
|
||||
void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) {
|
||||
BindInstr* load_saved_context =
|
||||
new BindInstr(temp_index(),
|
||||
new LoadLocalComp(variable, owner()->context_level()));
|
||||
new BindInstr(new LoadLocalComp(variable, owner()->context_level()));
|
||||
AddInstruction(load_saved_context);
|
||||
DoInstr* store_context =
|
||||
new DoInstr(new StoreContextComp(new UseVal(load_saved_context)));
|
||||
|
@ -161,8 +169,7 @@ void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) {
|
|||
void TestGraphVisitor::ReturnValue(Value* value) {
|
||||
if (FLAG_enable_type_checks) {
|
||||
BindInstr* assert_boolean =
|
||||
new BindInstr(temp_index(),
|
||||
new AssertBooleanComp(condition_token_index(),
|
||||
new BindInstr(new AssertBooleanComp(condition_token_index(),
|
||||
owner()->try_index(),
|
||||
value));
|
||||
AddInstruction(assert_boolean);
|
||||
|
@ -189,7 +196,7 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
|||
Append(for_value);
|
||||
|
||||
for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
|
||||
EffectGraphVisitor for_effect(owner(), for_value.temp_index());
|
||||
EffectGraphVisitor for_effect(owner(), temp_index());
|
||||
node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
|
||||
Append(for_effect);
|
||||
if (!is_open()) return;
|
||||
|
@ -213,8 +220,7 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
|||
return_value = BuildAssignableValue(node->value(),
|
||||
return_value,
|
||||
dst_type,
|
||||
dst_name,
|
||||
temp_index());
|
||||
dst_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,8 +324,7 @@ void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) {
|
|||
ReturnValue(BuildAssignableValue(node->expr(),
|
||||
for_value.value(),
|
||||
node->type(),
|
||||
node->dst_name(),
|
||||
temp_index()));
|
||||
node->dst_name()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -348,7 +353,7 @@ void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
|||
ValueGraphVisitor for_left_value(owner(), temp_index());
|
||||
node->left()->Visit(&for_left_value);
|
||||
Append(for_left_value);
|
||||
ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
||||
ValueGraphVisitor for_right_value(owner(), temp_index());
|
||||
node->right()->Visit(&for_right_value);
|
||||
Append(for_right_value);
|
||||
ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
|
||||
|
@ -387,19 +392,17 @@ void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
|||
Value* right_value = for_right.value();
|
||||
if (FLAG_enable_type_checks) {
|
||||
BindInstr* assert_boolean =
|
||||
new BindInstr(temp_index(),
|
||||
new AssertBooleanComp(node->right()->token_index(),
|
||||
new BindInstr(new AssertBooleanComp(node->right()->token_index(),
|
||||
owner()->try_index(),
|
||||
right_value));
|
||||
for_right.AddInstruction(assert_boolean);
|
||||
right_value = new UseVal(assert_boolean);
|
||||
}
|
||||
BindInstr* constant_true =
|
||||
new BindInstr(temp_index(), new ConstantVal(bool_true));
|
||||
BindInstr* constant_true = new BindInstr(new ConstantVal(bool_true));
|
||||
for_right.AddInstruction(constant_true);
|
||||
StrictCompareComp* comp = new StrictCompareComp(Token::kEQ_STRICT,
|
||||
right_value, new UseVal(constant_true));
|
||||
for_right.AddInstruction(new BindInstr(temp_index(), comp));
|
||||
for_right.AddInstruction(new BindInstr(comp));
|
||||
|
||||
if (node->kind() == Token::kAND) {
|
||||
ValueGraphVisitor for_false(owner(), temp_index());
|
||||
|
@ -411,7 +414,7 @@ void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
|||
for_true.ReturnComputation(new ConstantVal(bool_true));
|
||||
Join(for_test, for_true, for_right);
|
||||
}
|
||||
ReturnValue(new TempVal(AllocateTempIndex()));
|
||||
ReturnValue(new TempVal(temp_index() - 1));
|
||||
return;
|
||||
}
|
||||
EffectGraphVisitor::VisitBinaryOpNode(node);
|
||||
|
@ -484,7 +487,7 @@ void EffectGraphVisitor::VisitStringConcatNode(StringConcatNode* node) {
|
|||
ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>();
|
||||
ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index());
|
||||
interpol_arg->Add(node->values());
|
||||
TranslateArgumentList(*interpol_arg, temp_index(), values);
|
||||
TranslateArgumentList(*interpol_arg, values);
|
||||
StaticCallComp* call =
|
||||
new StaticCallComp(node->token_index(),
|
||||
owner()->try_index(),
|
||||
|
@ -498,13 +501,12 @@ void EffectGraphVisitor::VisitStringConcatNode(StringConcatNode* node) {
|
|||
void EffectGraphVisitor::BuildAssertAssignable(intptr_t token_index,
|
||||
Value* value,
|
||||
const AbstractType& dst_type,
|
||||
const String& dst_name,
|
||||
intptr_t start_index) {
|
||||
const String& dst_name) {
|
||||
// Build the type check computation.
|
||||
Value* instantiator_type_arguments = NULL;
|
||||
if (!dst_type.IsInstantiated()) {
|
||||
instantiator_type_arguments =
|
||||
BuildInstantiatorTypeArguments(token_index, start_index + 1);
|
||||
BuildInstantiatorTypeArguments(token_index);
|
||||
}
|
||||
AssertAssignableComp* assert_assignable =
|
||||
new AssertAssignableComp(token_index,
|
||||
|
@ -520,8 +522,7 @@ void EffectGraphVisitor::BuildAssertAssignable(intptr_t token_index,
|
|||
Value* EffectGraphVisitor::BuildAssignableValue(AstNode* value_node,
|
||||
Value* value,
|
||||
const AbstractType& dst_type,
|
||||
const String& dst_name,
|
||||
intptr_t start_index) {
|
||||
const String& dst_name) {
|
||||
if (CanSkipTypeCheck(value_node, dst_type)) {
|
||||
return value;
|
||||
}
|
||||
|
@ -530,12 +531,10 @@ Value* EffectGraphVisitor::BuildAssignableValue(AstNode* value_node,
|
|||
Value* instantiator_type_arguments = NULL;
|
||||
if (!dst_type.IsInstantiated()) {
|
||||
instantiator_type_arguments =
|
||||
BuildInstantiatorTypeArguments(value_node->token_index(),
|
||||
start_index + 1);
|
||||
BuildInstantiatorTypeArguments(value_node->token_index());
|
||||
}
|
||||
BindInstr* assert_assignable =
|
||||
new BindInstr(start_index,
|
||||
new AssertAssignableComp(value_node->token_index(),
|
||||
new BindInstr(new AssertAssignableComp(value_node->token_index(),
|
||||
owner()->try_index(),
|
||||
value,
|
||||
instantiator_type_arguments,
|
||||
|
@ -609,8 +608,7 @@ void ValueGraphVisitor::BuildInstanceOf(ComparisonNode* node) {
|
|||
Value* type_arguments = NULL;
|
||||
if (!type.IsInstantiated()) {
|
||||
type_arguments =
|
||||
BuildInstantiatorTypeArguments(node->token_index(),
|
||||
for_left_value.temp_index());
|
||||
BuildInstantiatorTypeArguments(node->token_index());
|
||||
}
|
||||
InstanceOfComp* instance_of =
|
||||
new InstanceOfComp(node->token_index(),
|
||||
|
@ -637,7 +635,7 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
|||
ValueGraphVisitor for_left_value(owner(), temp_index());
|
||||
node->left()->Visit(&for_left_value);
|
||||
Append(for_left_value);
|
||||
ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
||||
ValueGraphVisitor for_right_value(owner(), temp_index());
|
||||
node->right()->Visit(&for_right_value);
|
||||
Append(for_right_value);
|
||||
StrictCompareComp* comp = new StrictCompareComp(
|
||||
|
@ -650,7 +648,7 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
|||
ValueGraphVisitor for_left_value(owner(), temp_index());
|
||||
node->left()->Visit(&for_left_value);
|
||||
Append(for_left_value);
|
||||
ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
||||
ValueGraphVisitor for_right_value(owner(), temp_index());
|
||||
node->right()->Visit(&for_right_value);
|
||||
Append(for_right_value);
|
||||
EqualityCompareComp* comp = new EqualityCompareComp(
|
||||
|
@ -659,12 +657,11 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
|||
if (node->kind() == Token::kEQ) {
|
||||
ReturnComputation(comp);
|
||||
} else {
|
||||
Definition* eq_result = new BindInstr(temp_index(), comp);
|
||||
Definition* eq_result = new BindInstr(comp);
|
||||
AddInstruction(eq_result);
|
||||
if (FLAG_enable_type_checks) {
|
||||
eq_result =
|
||||
new BindInstr(temp_index(),
|
||||
new AssertBooleanComp(node->token_index(),
|
||||
new BindInstr(new AssertBooleanComp(node->token_index(),
|
||||
owner()->try_index(),
|
||||
new UseVal(eq_result)));
|
||||
AddInstruction(eq_result);
|
||||
|
@ -678,7 +675,7 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
|||
ValueGraphVisitor for_left_value(owner(), temp_index());
|
||||
node->left()->Visit(&for_left_value);
|
||||
Append(for_left_value);
|
||||
ValueGraphVisitor for_right_value(owner(), for_left_value.temp_index());
|
||||
ValueGraphVisitor for_right_value(owner(), temp_index());
|
||||
node->right()->Visit(&for_right_value);
|
||||
Append(for_right_value);
|
||||
ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
|
||||
|
@ -701,8 +698,7 @@ void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) {
|
|||
Value* value = for_value.value();
|
||||
if (FLAG_enable_type_checks) {
|
||||
BindInstr* assert_boolean =
|
||||
new BindInstr(temp_index(),
|
||||
new AssertBooleanComp(node->operand()->token_index(),
|
||||
new BindInstr(new AssertBooleanComp(node->operand()->token_index(),
|
||||
owner()->try_index(),
|
||||
value));
|
||||
AddInstruction(assert_boolean);
|
||||
|
@ -735,15 +731,12 @@ void EffectGraphVisitor::VisitIncrOpLocalNode(IncrOpLocalNode* node) {
|
|||
|
||||
// 1. Load the value.
|
||||
BindInstr* load =
|
||||
new BindInstr(temp_index(),
|
||||
new LoadLocalComp(node->local(), owner()->context_level()));
|
||||
new BindInstr(new LoadLocalComp(node->local(), owner()->context_level()));
|
||||
AddInstruction(load);
|
||||
AllocateTempIndex();
|
||||
// 2. Increment.
|
||||
Definition* incr =
|
||||
BuildIncrOpIncrement(node->kind(), node->token_index(), new UseVal(load));
|
||||
// 3. Perform the store, resulting in the new value.
|
||||
DeallocateTempIndex(); // Consuming incr.
|
||||
StoreLocalComp* store = new StoreLocalComp(
|
||||
node->local(), new UseVal(incr), owner()->context_level());
|
||||
ReturnComputation(store);
|
||||
|
@ -762,21 +755,16 @@ void ValueGraphVisitor::VisitIncrOpLocalNode(IncrOpLocalNode* node) {
|
|||
//
|
||||
// 1. Load the value.
|
||||
BindInstr* load =
|
||||
new BindInstr(temp_index(),
|
||||
new LoadLocalComp(node->local(), owner()->context_level()));
|
||||
new BindInstr(new LoadLocalComp(node->local(), owner()->context_level()));
|
||||
AddInstruction(load);
|
||||
AllocateTempIndex();
|
||||
// 2. Duplicate it to increment.
|
||||
PickTempInstr* duplicate =
|
||||
new PickTempInstr(temp_index(), load->temp_index());
|
||||
PickTempInstr* duplicate = new PickTempInstr(load->temp_index());
|
||||
AddInstruction(duplicate);
|
||||
AllocateTempIndex();
|
||||
// 3. Increment.
|
||||
Definition* incr =
|
||||
BuildIncrOpIncrement(node->kind(), node->token_index(),
|
||||
new UseVal(duplicate));
|
||||
// 4. Perform the store and return the original value.
|
||||
DeallocateTempIndex(); // Consuming incr.
|
||||
StoreLocalComp* store = new StoreLocalComp(
|
||||
node->local(), new UseVal(incr), owner()->context_level());
|
||||
AddInstruction(new DoInstr(store));
|
||||
|
@ -793,10 +781,8 @@ Definition* EffectGraphVisitor::BuildIncrOpFieldLoad(
|
|||
ValueGraphVisitor for_receiver(owner(), temp_index());
|
||||
node->receiver()->Visit(&for_receiver);
|
||||
Append(for_receiver);
|
||||
AllocateTempIndex();
|
||||
ASSERT(temp_index() == for_receiver.temp_index());
|
||||
PickTempInstr* duplicate =
|
||||
new PickTempInstr(temp_index(), temp_index() - 1);
|
||||
PickTempInstr* duplicate = new PickTempInstr(temp_index() - 1);
|
||||
AddInstruction(duplicate);
|
||||
|
||||
// Load the value.
|
||||
|
@ -806,13 +792,11 @@ Definition* EffectGraphVisitor::BuildIncrOpFieldLoad(
|
|||
ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(1);
|
||||
arguments->Add(new UseVal(duplicate));
|
||||
BindInstr* load =
|
||||
new BindInstr(temp_index(),
|
||||
new InstanceCallComp(
|
||||
new BindInstr(new InstanceCallComp(
|
||||
node->token_index(),
|
||||
owner()->try_index(), getter_name, arguments,
|
||||
Array::ZoneHandle(), 1));
|
||||
AddInstruction(load);
|
||||
AllocateTempIndex();
|
||||
|
||||
*receiver = for_receiver.value();
|
||||
return load;
|
||||
|
@ -827,22 +811,18 @@ Definition* EffectGraphVisitor::BuildIncrOpIncrement(Token::Kind kind,
|
|||
// t_n <- #1
|
||||
// t_n-1 <- InstanceCall(op, t_n-1, t_n)
|
||||
BindInstr* one =
|
||||
new BindInstr(temp_index(),
|
||||
new ConstantVal(Smi::ZoneHandle(Smi::New(1))));
|
||||
new BindInstr(new ConstantVal(Smi::ZoneHandle(Smi::New(1))));
|
||||
AddInstruction(one);
|
||||
ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
|
||||
arguments->Add(original);
|
||||
arguments->Add(new UseVal(one));
|
||||
const String& op_name =
|
||||
String::ZoneHandle(String::NewSymbol((kind == Token::kINCR) ? "+" : "-"));
|
||||
DeallocateTempIndex(); // Consuming original.
|
||||
BindInstr* add =
|
||||
new BindInstr(temp_index(),
|
||||
new InstanceCallComp(
|
||||
new BindInstr(new InstanceCallComp(
|
||||
token_index, owner()->try_index(), op_name,
|
||||
arguments, Array::ZoneHandle(), 2));
|
||||
AddInstruction(add);
|
||||
AllocateTempIndex();
|
||||
return add;
|
||||
}
|
||||
|
||||
|
@ -866,8 +846,6 @@ void EffectGraphVisitor::VisitIncrOpInstanceFieldNode(
|
|||
node->field_name(),
|
||||
receiver,
|
||||
new UseVal(incr));
|
||||
DeallocateTempIndex(); // Consuming incr.
|
||||
DeallocateTempIndex(); // Consuming receiver.
|
||||
ReturnComputation(store);
|
||||
}
|
||||
|
||||
|
@ -885,10 +863,8 @@ void ValueGraphVisitor::VisitIncrOpInstanceFieldNode(
|
|||
//
|
||||
// 1. Name a placeholder.
|
||||
BindInstr* placeholder =
|
||||
new BindInstr(temp_index(),
|
||||
new ConstantVal(Smi::ZoneHandle(Smi::New(0))));
|
||||
new BindInstr(new ConstantVal(Smi::ZoneHandle(Smi::New(0))));
|
||||
AddInstruction(placeholder);
|
||||
AllocateTempIndex();
|
||||
// 2. Load the value.
|
||||
Value* receiver = NULL;
|
||||
Definition* load = BuildIncrOpFieldLoad(node, &receiver);
|
||||
|
@ -907,8 +883,6 @@ void ValueGraphVisitor::VisitIncrOpInstanceFieldNode(
|
|||
InstanceCallComp* store = new InstanceCallComp(
|
||||
node->token_index(), owner()->try_index(),
|
||||
setter_name, arguments, Array::ZoneHandle(), 1);
|
||||
DeallocateTempIndex(); // Consuming incr.
|
||||
DeallocateTempIndex(); // Consuming receiver.
|
||||
AddInstruction(new DoInstr(store));
|
||||
ReturnValue(new UseVal(placeholder));
|
||||
}
|
||||
|
@ -924,24 +898,20 @@ Definition* EffectGraphVisitor::BuildIncrOpIndexedLoad(
|
|||
ValueGraphVisitor for_receiver(owner(), temp_index());
|
||||
node->array()->Visit(&for_receiver);
|
||||
Append(for_receiver);
|
||||
AllocateTempIndex();
|
||||
ASSERT(temp_index() == for_receiver.temp_index());
|
||||
|
||||
ValueGraphVisitor for_index(owner(), temp_index());
|
||||
node->index()->Visit(&for_index);
|
||||
Append(for_index);
|
||||
AllocateTempIndex();
|
||||
ASSERT(temp_index() == for_index.temp_index());
|
||||
|
||||
// Duplicate the receiver and index values, load the value.
|
||||
// t_n+2 <- Pick(t_n)
|
||||
// t_n+3 <- Pick(t_n+1)
|
||||
// t_n+2 <- InstanceCall([], t_n+2, t_n+3)
|
||||
PickTempInstr* duplicate_receiver =
|
||||
new PickTempInstr(temp_index(), temp_index() - 2);
|
||||
PickTempInstr* duplicate_receiver = new PickTempInstr(temp_index() - 2);
|
||||
AddInstruction(duplicate_receiver);
|
||||
PickTempInstr* duplicate_index =
|
||||
new PickTempInstr(temp_index() + 1, temp_index() - 1);
|
||||
PickTempInstr* duplicate_index = new PickTempInstr(temp_index() - 2);
|
||||
AddInstruction(duplicate_index);
|
||||
ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
|
||||
arguments->Add(new UseVal(duplicate_receiver));
|
||||
|
@ -949,13 +919,11 @@ Definition* EffectGraphVisitor::BuildIncrOpIndexedLoad(
|
|||
const String& load_name =
|
||||
String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX)));
|
||||
BindInstr* load =
|
||||
new BindInstr(temp_index(),
|
||||
new InstanceCallComp(
|
||||
new BindInstr(new InstanceCallComp(
|
||||
node->token_index(),
|
||||
owner()->try_index(), load_name, arguments,
|
||||
Array::ZoneHandle(), 1));
|
||||
AddInstruction(load);
|
||||
AllocateTempIndex();
|
||||
|
||||
*receiver = for_receiver.value();
|
||||
*index = for_index.value();
|
||||
|
@ -981,9 +949,6 @@ void EffectGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) {
|
|||
receiver,
|
||||
index,
|
||||
new UseVal(incr));
|
||||
DeallocateTempIndex(); // Consuming incr.
|
||||
DeallocateTempIndex(); // Consuming index.
|
||||
DeallocateTempIndex(); // Consuming receiver.
|
||||
ReturnComputation(store);
|
||||
}
|
||||
|
||||
|
@ -1000,10 +965,8 @@ void ValueGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) {
|
|||
//
|
||||
// 1. Name a placeholder.
|
||||
BindInstr* placeholder =
|
||||
new BindInstr(temp_index(),
|
||||
new ConstantVal(Smi::ZoneHandle(Smi::New(0))));
|
||||
new BindInstr(new ConstantVal(Smi::ZoneHandle(Smi::New(0))));
|
||||
AddInstruction(placeholder);
|
||||
AllocateTempIndex();
|
||||
// 2. Load the value.
|
||||
Value* receiver = NULL;
|
||||
Value* index = NULL;
|
||||
|
@ -1024,9 +987,6 @@ void ValueGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) {
|
|||
InstanceCallComp* store = new InstanceCallComp(
|
||||
node->token_index(), owner()->try_index(),
|
||||
store_name, arguments, Array::ZoneHandle(), 1);
|
||||
DeallocateTempIndex(); // Consuming incr.
|
||||
DeallocateTempIndex(); // Consuming index.
|
||||
DeallocateTempIndex(); // Consuming receiver.
|
||||
AddInstruction(new DoInstr(store));
|
||||
ReturnValue(new UseVal(placeholder));
|
||||
}
|
||||
|
@ -1059,23 +1019,15 @@ void ValueGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) {
|
|||
ValueGraphVisitor for_true(owner(), temp_index());
|
||||
node->true_expr()->Visit(&for_true);
|
||||
ASSERT(for_true.is_open());
|
||||
if (for_true.value()->IsTemp()) {
|
||||
ASSERT(for_true.value()->AsTemp()->index() == temp_index());
|
||||
} else {
|
||||
for_true.AddInstruction(new BindInstr(temp_index(), for_true.value()));
|
||||
}
|
||||
ASSERT(for_true.value()->IsTemp() || for_true.value()->IsUse());
|
||||
|
||||
ValueGraphVisitor for_false(owner(), temp_index());
|
||||
node->false_expr()->Visit(&for_false);
|
||||
ASSERT(for_false.is_open());
|
||||
if (for_false.value()->IsTemp()) {
|
||||
ASSERT(for_false.value()->AsTemp()->index() == temp_index());
|
||||
} else {
|
||||
for_false.AddInstruction(new BindInstr(temp_index(), for_false.value()));
|
||||
}
|
||||
ASSERT(for_false.value()->IsTemp() || for_false.value()->IsUse());
|
||||
|
||||
Join(for_test, for_true, for_false);
|
||||
ReturnValue(new TempVal(AllocateTempIndex()));
|
||||
ReturnValue(new TempVal(temp_index() - 1));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1477,13 +1429,11 @@ void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
|
|||
// Translate the array elements and collect their values.
|
||||
ZoneGrowableArray<Value*>* values =
|
||||
new ZoneGrowableArray<Value*>(node->length());
|
||||
int index = temp_index();
|
||||
for (int i = 0; i < node->length(); ++i) {
|
||||
ValueGraphVisitor for_value(owner(), index);
|
||||
ValueGraphVisitor for_value(owner(), temp_index());
|
||||
node->ElementAt(i)->Visit(&for_value);
|
||||
Append(for_value);
|
||||
values->Add(for_value.value());
|
||||
index = for_value.temp_index();
|
||||
}
|
||||
CreateArrayComp* create = new CreateArrayComp(node,
|
||||
owner()->try_index(),
|
||||
|
@ -1495,7 +1445,6 @@ void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
|
|||
void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
|
||||
const Function& function = node->function();
|
||||
|
||||
int next_index = temp_index();
|
||||
if (function.IsNonImplicitClosureFunction()) {
|
||||
const ContextScope& context_scope = ContextScope::ZoneHandle(
|
||||
node->scope()->PreserveOuterScope(owner()->context_level()));
|
||||
|
@ -1506,10 +1455,6 @@ void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
|
|||
ValueGraphVisitor for_receiver(owner(), temp_index());
|
||||
node->receiver()->Visit(&for_receiver);
|
||||
Append(for_receiver);
|
||||
if (!for_receiver.value()->IsTemp()) {
|
||||
AddInstruction(new BindInstr(temp_index(), for_receiver.value()));
|
||||
}
|
||||
++next_index;
|
||||
}
|
||||
ASSERT(function.context_scope() != ContextScope::null());
|
||||
|
||||
|
@ -1522,7 +1467,7 @@ void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
|
|||
if (requires_type_arguments) {
|
||||
ASSERT(!function.IsImplicitStaticClosureFunction());
|
||||
type_arguments =
|
||||
BuildInstantiatorTypeArguments(node->token_index(), temp_index());
|
||||
BuildInstantiatorTypeArguments(node->token_index());
|
||||
}
|
||||
|
||||
CreateClosureComp* create =
|
||||
|
@ -1533,13 +1478,11 @@ void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
|
|||
|
||||
void EffectGraphVisitor::TranslateArgumentList(
|
||||
const ArgumentListNode& node,
|
||||
intptr_t next_temp_index,
|
||||
ZoneGrowableArray<Value*>* values) {
|
||||
for (intptr_t i = 0; i < node.length(); ++i) {
|
||||
ValueGraphVisitor for_argument(owner(), next_temp_index);
|
||||
ValueGraphVisitor for_argument(owner(), temp_index());
|
||||
node.NodeAt(i)->Visit(&for_argument);
|
||||
Append(for_argument);
|
||||
next_temp_index = for_argument.temp_index();
|
||||
values->Add(for_argument.value());
|
||||
}
|
||||
}
|
||||
|
@ -1554,7 +1497,7 @@ void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
|
|||
Append(for_receiver);
|
||||
values->Add(for_receiver.value());
|
||||
|
||||
TranslateArgumentList(*arguments, for_receiver.temp_index(), values);
|
||||
TranslateArgumentList(*arguments, values);
|
||||
InstanceCallComp* call = new InstanceCallComp(
|
||||
node->token_index(), owner()->try_index(),
|
||||
node->function_name(), values,
|
||||
|
@ -1568,7 +1511,7 @@ void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
|
|||
void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
|
||||
int length = node->arguments()->length();
|
||||
ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>(length);
|
||||
TranslateArgumentList(*node->arguments(), temp_index(), values);
|
||||
TranslateArgumentList(*node->arguments(), values);
|
||||
StaticCallComp* call =
|
||||
new StaticCallComp(node->token_index(),
|
||||
owner()->try_index(),
|
||||
|
@ -1582,17 +1525,17 @@ void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
|
|||
void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) {
|
||||
// Context is saved around the call, it's treated as an extra operand
|
||||
// consumed by the call (but not an argument).
|
||||
BindInstr* context = new BindInstr(temp_index(), new CurrentContextComp());
|
||||
BindInstr* context = new BindInstr(new CurrentContextComp());
|
||||
AddInstruction(context);
|
||||
|
||||
ValueGraphVisitor for_closure(owner(), temp_index() + 1);
|
||||
ValueGraphVisitor for_closure(owner(), temp_index());
|
||||
node->closure()->Visit(&for_closure);
|
||||
Append(for_closure);
|
||||
|
||||
ZoneGrowableArray<Value*>* arguments =
|
||||
new ZoneGrowableArray<Value*>(node->arguments()->length());
|
||||
arguments->Add(for_closure.value());
|
||||
TranslateArgumentList(*node->arguments(), temp_index() + 2, arguments);
|
||||
TranslateArgumentList(*node->arguments(), arguments);
|
||||
// First operand is the saved context, consumed by the call.
|
||||
ClosureCallComp* call = new ClosureCallComp(node,
|
||||
owner()->try_index(),
|
||||
|
@ -1603,11 +1546,10 @@ void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) {
|
|||
|
||||
|
||||
void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) {
|
||||
BindInstr* context = new BindInstr(temp_index(), new CurrentContextComp());
|
||||
BindInstr* context = new BindInstr(new CurrentContextComp());
|
||||
AddInstruction(context);
|
||||
BindInstr* clone =
|
||||
new BindInstr(temp_index(),
|
||||
new CloneContextComp(node->token_index(),
|
||||
new BindInstr(new CloneContextComp(node->token_index(),
|
||||
owner()->try_index(),
|
||||
new UseVal(context)));
|
||||
AddInstruction(clone);
|
||||
|
@ -1649,9 +1591,8 @@ Definition* EffectGraphVisitor::BuildObjectAllocation(
|
|||
owner()->try_index(),
|
||||
allocate_arguments);
|
||||
}
|
||||
BindInstr* allocate = new BindInstr(temp_index(), allocate_comp);
|
||||
BindInstr* allocate = new BindInstr(allocate_comp);
|
||||
AddInstruction(allocate);
|
||||
AllocateTempIndex();
|
||||
return allocate;
|
||||
}
|
||||
|
||||
|
@ -1659,25 +1600,21 @@ Definition* EffectGraphVisitor::BuildObjectAllocation(
|
|||
void EffectGraphVisitor::BuildConstructorCall(ConstructorCallNode* node,
|
||||
Value* alloc_value) {
|
||||
BindInstr* ctor_arg =
|
||||
new BindInstr(temp_index(),
|
||||
new ConstantVal(
|
||||
new BindInstr(new ConstantVal(
|
||||
Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))));
|
||||
AddInstruction(ctor_arg);
|
||||
AllocateTempIndex();
|
||||
|
||||
ZoneGrowableArray<Value*>* values = new ZoneGrowableArray<Value*>();
|
||||
values->Add(alloc_value);
|
||||
values->Add(new UseVal(ctor_arg));
|
||||
|
||||
TranslateArgumentList(*node->arguments(), temp_index(), values);
|
||||
TranslateArgumentList(*node->arguments(), values);
|
||||
StaticCallComp* call =
|
||||
new StaticCallComp(node->token_index(),
|
||||
owner()->try_index(),
|
||||
node->constructor(),
|
||||
node->arguments()->names(),
|
||||
values);
|
||||
DeallocateTempIndex(); // Consuming ctor_arg.
|
||||
DeallocateTempIndex(); // Consuming alloc_value.
|
||||
AddInstruction(new DoInstr(call));
|
||||
}
|
||||
|
||||
|
@ -1688,16 +1625,13 @@ void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
|
|||
new ZoneGrowableArray<Value*>();
|
||||
factory_arguments->Add(new UseVal(BuildFactoryTypeArguments(node)));
|
||||
ASSERT(factory_arguments->length() == 1);
|
||||
TranslateArgumentList(*node->arguments(),
|
||||
temp_index(),
|
||||
factory_arguments);
|
||||
TranslateArgumentList(*node->arguments(), factory_arguments);
|
||||
StaticCallComp* call =
|
||||
new StaticCallComp(node->token_index(),
|
||||
owner()->try_index(),
|
||||
node->constructor(),
|
||||
node->arguments()->names(),
|
||||
factory_arguments);
|
||||
DeallocateTempIndex(); // Consuming type arguments.
|
||||
ReturnComputation(call);
|
||||
return;
|
||||
}
|
||||
|
@ -1713,7 +1647,7 @@ void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
|
|||
|
||||
|
||||
Value* EffectGraphVisitor::BuildInstantiatorTypeArguments(
|
||||
intptr_t token_index, intptr_t start_index) {
|
||||
intptr_t token_index) {
|
||||
const Class& instantiator_class = Class::Handle(
|
||||
owner()->parsed_function().function().owner());
|
||||
if (instantiator_class.NumTypeParameters() == 0) {
|
||||
|
@ -1725,13 +1659,12 @@ Value* EffectGraphVisitor::BuildInstantiatorTypeArguments(
|
|||
type ^= ClassFinalizer::FinalizeType(
|
||||
instantiator_class, type, ClassFinalizer::kFinalizeWellFormed);
|
||||
type_arguments = type.arguments();
|
||||
BindInstr* args =
|
||||
new BindInstr(temp_index(), new ConstantVal(type_arguments));
|
||||
BindInstr* args = new BindInstr(new ConstantVal(type_arguments));
|
||||
AddInstruction(args);
|
||||
return new UseVal(args);
|
||||
}
|
||||
ASSERT(owner()->parsed_function().instantiator() != NULL);
|
||||
ValueGraphVisitor for_instantiator(owner(), start_index);
|
||||
ValueGraphVisitor for_instantiator(owner(), temp_index());
|
||||
owner()->parsed_function().instantiator()->Visit(&for_instantiator);
|
||||
Append(for_instantiator);
|
||||
Function& outer_function =
|
||||
|
@ -1753,8 +1686,7 @@ Value* EffectGraphVisitor::BuildInstantiatorTypeArguments(
|
|||
ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments);
|
||||
|
||||
BindInstr* load =
|
||||
new BindInstr(start_index,
|
||||
new NativeLoadFieldComp(
|
||||
new BindInstr(new NativeLoadFieldComp(
|
||||
for_instantiator.value(),
|
||||
type_arguments_instance_field_offset));
|
||||
AddInstruction(load);
|
||||
|
@ -1768,21 +1700,18 @@ Definition* EffectGraphVisitor::BuildFactoryTypeArguments(
|
|||
if (node->type_arguments().IsNull() ||
|
||||
node->type_arguments().IsInstantiated()) {
|
||||
BindInstr* type_args =
|
||||
new BindInstr(temp_index(), new ConstantVal(node->type_arguments()));
|
||||
new BindInstr(new ConstantVal(node->type_arguments()));
|
||||
AddInstruction(type_args);
|
||||
AllocateTempIndex();
|
||||
return type_args;
|
||||
}
|
||||
// The type arguments are uninstantiated.
|
||||
Value* instantiator_value =
|
||||
BuildInstantiatorTypeArguments(node->token_index(), temp_index());
|
||||
BuildInstantiatorTypeArguments(node->token_index());
|
||||
BindInstr* extract =
|
||||
new BindInstr(temp_index(),
|
||||
new ExtractFactoryTypeArgumentsComp(node,
|
||||
new BindInstr(new ExtractFactoryTypeArgumentsComp(node,
|
||||
owner()->try_index(),
|
||||
instantiator_value));
|
||||
AddInstruction(extract);
|
||||
AllocateTempIndex();
|
||||
return extract;
|
||||
}
|
||||
|
||||
|
@ -1795,12 +1724,11 @@ void EffectGraphVisitor::BuildConstructorTypeArguments(
|
|||
if (node->type_arguments().IsNull() ||
|
||||
node->type_arguments().IsInstantiated()) {
|
||||
BindInstr* type_args =
|
||||
new BindInstr(temp_index(), new ConstantVal(node->type_arguments()));
|
||||
new BindInstr(new ConstantVal(node->type_arguments()));
|
||||
AddInstruction(type_args);
|
||||
// No instantiator required.
|
||||
BindInstr* no_instantiator =
|
||||
new BindInstr(temp_index() + 1,
|
||||
new ConstantVal(
|
||||
new BindInstr(new ConstantVal(
|
||||
Smi::ZoneHandle(Smi::New(
|
||||
StubCode::kNoInstantiator))));
|
||||
AddInstruction(no_instantiator);
|
||||
|
@ -1811,26 +1739,22 @@ void EffectGraphVisitor::BuildConstructorTypeArguments(
|
|||
// The type arguments are uninstantiated.
|
||||
// Place holder to hold uninstantiated constructor type arguments.
|
||||
BindInstr* placeholder =
|
||||
new BindInstr(temp_index(),
|
||||
new ConstantVal(Object::ZoneHandle()));
|
||||
new BindInstr(new ConstantVal(Object::ZoneHandle()));
|
||||
AddInstruction(placeholder);
|
||||
Value* instantiator =
|
||||
BuildInstantiatorTypeArguments(node->token_index(), temp_index() + 1);
|
||||
BuildInstantiatorTypeArguments(node->token_index());
|
||||
ASSERT(instantiator->IsUse());
|
||||
PickTempInstr* duplicate_instantiator =
|
||||
new PickTempInstr(temp_index() + 2,
|
||||
instantiator->AsUse()->definition()->temp_index());
|
||||
new PickTempInstr(instantiator->AsUse()->definition()->temp_index());
|
||||
AddInstruction(duplicate_instantiator);
|
||||
BindInstr* extract_type_arguments =
|
||||
new BindInstr(temp_index() + 2,
|
||||
new ExtractConstructorTypeArgumentsComp(
|
||||
new BindInstr(new ExtractConstructorTypeArgumentsComp(
|
||||
node, new UseVal(duplicate_instantiator)));
|
||||
AddInstruction(extract_type_arguments);
|
||||
AddInstruction(new TuckTempInstr(placeholder->temp_index(),
|
||||
extract_type_arguments->temp_index()));
|
||||
BindInstr* extract_instantiator =
|
||||
new BindInstr(temp_index() + 1,
|
||||
new ExtractConstructorInstantiatorComp(
|
||||
new BindInstr(new ExtractConstructorInstantiatorComp(
|
||||
node,
|
||||
instantiator,
|
||||
new UseVal(extract_type_arguments)));
|
||||
|
@ -1854,10 +1778,8 @@ void ValueGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
|
|||
// StaticCall(constructor, t_n+1, t_n+2, ...)
|
||||
|
||||
Definition* allocate = BuildObjectAllocation(node);
|
||||
PickTempInstr* duplicate =
|
||||
new PickTempInstr(temp_index(), allocate->temp_index());
|
||||
PickTempInstr* duplicate = new PickTempInstr(allocate->temp_index());
|
||||
AddInstruction(duplicate);
|
||||
AllocateTempIndex();
|
||||
BuildConstructorCall(node, new UseVal(duplicate));
|
||||
ReturnValue(new UseVal(allocate));
|
||||
}
|
||||
|
@ -1970,8 +1892,7 @@ void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) {
|
|||
store_value = BuildAssignableValue(node->value(),
|
||||
store_value,
|
||||
node->local().type(),
|
||||
node->local().name(),
|
||||
temp_index());
|
||||
node->local().name());
|
||||
}
|
||||
StoreLocalComp* store =
|
||||
new StoreLocalComp(node->local(), store_value, owner()->context_level());
|
||||
|
@ -2005,8 +1926,7 @@ void EffectGraphVisitor::VisitStoreInstanceFieldNode(
|
|||
store_value = BuildAssignableValue(node->value(),
|
||||
store_value,
|
||||
type,
|
||||
dst_name,
|
||||
for_instance.temp_index());
|
||||
dst_name);
|
||||
}
|
||||
StoreInstanceFieldComp* store =
|
||||
new StoreInstanceFieldComp(node, for_instance.value(), store_value);
|
||||
|
@ -2031,8 +1951,7 @@ void EffectGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
|
|||
store_value = BuildAssignableValue(node->value(),
|
||||
store_value,
|
||||
type,
|
||||
dst_name,
|
||||
temp_index());
|
||||
dst_name);
|
||||
}
|
||||
StoreStaticFieldComp* store =
|
||||
new StoreStaticFieldComp(node->field(), store_value);
|
||||
|
@ -2085,11 +2004,10 @@ bool EffectGraphVisitor::MustSaveRestoreContext(SequenceNode* node) const {
|
|||
|
||||
|
||||
void EffectGraphVisitor::UnchainContext() {
|
||||
BindInstr* context = new BindInstr(temp_index(), new CurrentContextComp());
|
||||
BindInstr* context = new BindInstr(new CurrentContextComp());
|
||||
AddInstruction(context);
|
||||
BindInstr* parent =
|
||||
new BindInstr(temp_index(),
|
||||
new NativeLoadFieldComp(
|
||||
new BindInstr(new NativeLoadFieldComp(
|
||||
new UseVal(context), Context::parent_offset()));
|
||||
AddInstruction(parent);
|
||||
AddInstruction(new DoInstr(new StoreContextComp(new UseVal(parent))));
|
||||
|
@ -2109,8 +2027,7 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
// Allocate and chain a new context.
|
||||
// Allocate context computation (uses current CTX)
|
||||
BindInstr* allocated_context =
|
||||
new BindInstr(temp_index(),
|
||||
new AllocateContextComp(node->token_index(),
|
||||
new BindInstr(new AllocateContextComp(node->token_index(),
|
||||
owner()->try_index(),
|
||||
num_context_variables));
|
||||
AddInstruction(allocated_context);
|
||||
|
@ -2120,8 +2037,7 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
// parent of the newly allocated context, as it is not accessible. Instead,
|
||||
// save it in a pre-allocated variable and restore it on exit.
|
||||
if (MustSaveRestoreContext(node)) {
|
||||
BindInstr* current_context =
|
||||
new BindInstr(temp_index() + 1, new CurrentContextComp());
|
||||
BindInstr* current_context = new BindInstr(new CurrentContextComp());
|
||||
AddInstruction(current_context);
|
||||
StoreLocalComp* store_local = new StoreLocalComp(
|
||||
*owner()->parsed_function().saved_context_var(),
|
||||
|
@ -2129,8 +2045,7 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
0);
|
||||
AddInstruction(new DoInstr(store_local));
|
||||
BindInstr* null_context =
|
||||
new BindInstr(temp_index() + 1,
|
||||
new ConstantVal(Object::ZoneHandle()));
|
||||
new BindInstr(new ConstantVal(Object::ZoneHandle()));
|
||||
AddInstruction(null_context);
|
||||
StoreContextComp* store_context =
|
||||
new StoreContextComp(new UseVal(null_context));
|
||||
|
@ -2165,8 +2080,7 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
|
||||
// Copy parameter from local frame to current context.
|
||||
BindInstr* load =
|
||||
new BindInstr(temp_index(),
|
||||
new LoadLocalComp(*temp_local,
|
||||
new BindInstr(new LoadLocalComp(*temp_local,
|
||||
owner()->context_level()));
|
||||
AddInstruction(load);
|
||||
StoreLocalComp* store_local = new StoreLocalComp(
|
||||
|
@ -2178,8 +2092,7 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
// allow GC of passed value if it gets overwritten by a new value in
|
||||
// the function.
|
||||
BindInstr* null_constant =
|
||||
new BindInstr(temp_index(),
|
||||
new ConstantVal(Object::ZoneHandle()));
|
||||
new BindInstr(new ConstantVal(Object::ZoneHandle()));
|
||||
AddInstruction(null_constant);
|
||||
StoreLocalComp* clear_local = new StoreLocalComp(
|
||||
*temp_local,
|
||||
|
@ -2200,15 +2113,13 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
ASSERT(parameter.owner() == scope);
|
||||
if (!CanSkipTypeCheck(NULL, parameter.type())) {
|
||||
BindInstr* load =
|
||||
new BindInstr(temp_index(),
|
||||
new LoadLocalComp(parameter,
|
||||
new BindInstr(new LoadLocalComp(parameter,
|
||||
owner()->context_level()));
|
||||
AddInstruction(load);
|
||||
BuildAssertAssignable(parameter.token_index(),
|
||||
new UseVal(load),
|
||||
parameter.type(),
|
||||
parameter.name(),
|
||||
temp_index());
|
||||
parameter.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,6 @@ class EffectGraphVisitor : public AstNodeVisitor {
|
|||
protected:
|
||||
// Helpers for translating parts of the AST.
|
||||
void TranslateArgumentList(const ArgumentListNode& node,
|
||||
intptr_t next_temp_index,
|
||||
ZoneGrowableArray<Value*>* values);
|
||||
|
||||
// Build the load part of a instance field increment. Translates the
|
||||
|
@ -151,22 +150,19 @@ class EffectGraphVisitor : public AstNodeVisitor {
|
|||
ZoneGrowableArray<Value*>* args);
|
||||
|
||||
// Returns the value of the type arguments of the instantiator.
|
||||
Value* BuildInstantiatorTypeArguments(intptr_t token_index,
|
||||
intptr_t start_index);
|
||||
Value* BuildInstantiatorTypeArguments(intptr_t token_index);
|
||||
|
||||
// Perform a type check on the given value.
|
||||
void BuildAssertAssignable(intptr_t token_index,
|
||||
Value* value,
|
||||
const AbstractType& dst_type,
|
||||
const String& dst_name,
|
||||
intptr_t start_index);
|
||||
const String& dst_name);
|
||||
|
||||
// Perform a type check on the given value and return it.
|
||||
Value* BuildAssignableValue(AstNode* value_node,
|
||||
Value* value,
|
||||
const AbstractType& dst_type,
|
||||
const String& dst_name,
|
||||
intptr_t start_index);
|
||||
const String& dst_name);
|
||||
|
||||
virtual void BuildInstanceOf(ComparisonNode* node);
|
||||
|
||||
|
@ -177,7 +173,10 @@ class EffectGraphVisitor : public AstNodeVisitor {
|
|||
|
||||
void CloseFragment() { exit_ = NULL; }
|
||||
intptr_t AllocateTempIndex() { return temp_index_++; }
|
||||
void DeallocateTempIndex() { --temp_index_; }
|
||||
void DeallocateTempIndex(intptr_t n) {
|
||||
ASSERT(temp_index_ >= n);
|
||||
temp_index_ -= n;
|
||||
}
|
||||
|
||||
virtual void CompiletimeStringInterpolation(const Function& interpol_func,
|
||||
const Array& literals);
|
||||
|
@ -248,10 +247,9 @@ class ValueGraphVisitor : public EffectGraphVisitor {
|
|||
// the graph and returns its temporary value (i.e., set the output
|
||||
// parameters).
|
||||
virtual void ReturnComputation(Computation* computation) {
|
||||
BindInstr* defn = new BindInstr(temp_index(), computation);
|
||||
BindInstr* defn = new BindInstr(computation);
|
||||
AddInstruction(defn);
|
||||
AllocateTempIndex();
|
||||
value_ = new UseVal(defn);
|
||||
ReturnValue(new UseVal(defn));
|
||||
}
|
||||
|
||||
virtual void CompiletimeStringInterpolation(const Function& interpol_func,
|
||||
|
@ -305,14 +303,6 @@ class TestGraphVisitor : public ValueGraphVisitor {
|
|||
// Closes the fragment and sets the output parameters.
|
||||
virtual void ReturnValue(Value* value);
|
||||
|
||||
// Specify a computation as the final result. Adds a Bind instruction to
|
||||
// the graph and branches on its value.
|
||||
virtual void ReturnComputation(Computation* computation) {
|
||||
BindInstr* defn = new BindInstr(temp_index(), computation);
|
||||
AddInstruction(defn);
|
||||
ReturnValue(new UseVal(defn));
|
||||
}
|
||||
|
||||
// Output parameters.
|
||||
TargetEntryInstr** true_successor_address_;
|
||||
TargetEntryInstr** false_successor_address_;
|
||||
|
|
|
@ -92,6 +92,106 @@ void FlowGraphVisitor::VisitBlocks() {
|
|||
}
|
||||
|
||||
|
||||
// ==== Per-instruction input counts.
|
||||
intptr_t AssertAssignableComp::InputCount() const {
|
||||
// Value and optional instantiator type arguments.
|
||||
return (instantiator_type_arguments() == NULL) ? 1 : 2;
|
||||
}
|
||||
|
||||
|
||||
intptr_t InstanceOfComp::InputCount() const {
|
||||
// Value and optional type_arguments.
|
||||
return (type_arguments() == NULL) ? 1 : 2;
|
||||
}
|
||||
|
||||
|
||||
intptr_t CreateClosureComp::InputCount() const {
|
||||
// Optional type arguments.
|
||||
return (type_arguments() == NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t InstanceCallComp::InputCount() const {
|
||||
return ArgumentCount();
|
||||
}
|
||||
|
||||
|
||||
intptr_t StaticCallComp::InputCount() const {
|
||||
return ArgumentCount();
|
||||
}
|
||||
|
||||
|
||||
intptr_t ClosureCallComp::InputCount() const {
|
||||
// Context and arguments.
|
||||
return 1 + ArgumentCount();
|
||||
}
|
||||
|
||||
|
||||
intptr_t AllocateObjectComp::InputCount() const {
|
||||
return arguments().length();
|
||||
}
|
||||
|
||||
|
||||
intptr_t AllocateObjectWithBoundsCheckComp::InputCount() const {
|
||||
return arguments().length();
|
||||
}
|
||||
|
||||
|
||||
intptr_t CreateArrayComp::InputCount() const {
|
||||
return ElementCount();
|
||||
}
|
||||
|
||||
|
||||
intptr_t BranchInstr::InputCount() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ReThrowInstr::InputCount() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ThrowInstr::InputCount() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ReturnInstr::InputCount() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t BindInstr::InputCount() const {
|
||||
return computation()->InputCount();
|
||||
}
|
||||
|
||||
|
||||
intptr_t DoInstr::InputCount() const {
|
||||
return computation()->InputCount();
|
||||
}
|
||||
|
||||
|
||||
intptr_t TuckTempInstr::InputCount() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
intptr_t PickTempInstr::InputCount() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
intptr_t TargetEntryInstr::InputCount() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
intptr_t JoinEntryInstr::InputCount() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ==== Postorder graph traversal.
|
||||
void JoinEntryInstr::DiscoverBlocks(
|
||||
BlockEntryInstr* current_block,
|
||||
|
|
|
@ -79,6 +79,8 @@ class Computation : public ZoneAllocated {
|
|||
// Visiting support.
|
||||
virtual void Accept(FlowGraphVisitor* visitor) = 0;
|
||||
|
||||
virtual intptr_t InputCount() const = 0;
|
||||
|
||||
private:
|
||||
friend class Instruction;
|
||||
static intptr_t GetNextCid() {
|
||||
|
@ -94,7 +96,49 @@ class Computation : public ZoneAllocated {
|
|||
};
|
||||
|
||||
|
||||
class Value : public Computation {
|
||||
// An embedded container with N elements of type T. Used (with partial
|
||||
// specialization for N=0) because embedded arrays cannot have size 0.
|
||||
template<typename T, intptr_t N>
|
||||
class EmbeddedArray {
|
||||
public:
|
||||
EmbeddedArray() : elements_() { }
|
||||
|
||||
intptr_t length() { return N; }
|
||||
T& operator[](intptr_t i) {
|
||||
ASSERT(i < length());
|
||||
return elements_[i];
|
||||
}
|
||||
|
||||
private:
|
||||
T elements_[N];
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class EmbeddedArray<T, 0> {
|
||||
public:
|
||||
int length() { return 0; }
|
||||
T& operator[](intptr_t i) {
|
||||
UNREACHABLE();
|
||||
static T sentinel = 0;
|
||||
return sentinel;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Value;
|
||||
|
||||
template<intptr_t N>
|
||||
class TemplateComputation : public Computation {
|
||||
public:
|
||||
virtual intptr_t InputCount() const { return N; }
|
||||
|
||||
protected:
|
||||
EmbeddedArray<Value*, N> inputs_;
|
||||
};
|
||||
|
||||
|
||||
class Value : public TemplateComputation<0> {
|
||||
public:
|
||||
Value() { }
|
||||
|
||||
|
@ -112,7 +156,7 @@ class Value : public Computation {
|
|||
|
||||
// Functions defined in all concrete computation classes.
|
||||
#define DECLARE_COMPUTATION(ShortName) \
|
||||
virtual void Accept(FlowGraphVisitor* visitor);
|
||||
virtual void Accept(FlowGraphVisitor* visitor); \
|
||||
|
||||
// Functions defined in all concrete value classes.
|
||||
#define DECLARE_VALUE(ShortName) \
|
||||
|
@ -202,6 +246,8 @@ class AssertAssignableComp : public Computation {
|
|||
const AbstractType& dst_type() const { return dst_type_; }
|
||||
const String& dst_name() const { return dst_name_; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -214,27 +260,26 @@ class AssertAssignableComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class AssertBooleanComp : public Computation {
|
||||
class AssertBooleanComp : public TemplateComputation<1> {
|
||||
public:
|
||||
AssertBooleanComp(intptr_t token_index,
|
||||
intptr_t try_index,
|
||||
Value* value)
|
||||
: token_index_(token_index),
|
||||
try_index_(try_index),
|
||||
value_(value) {
|
||||
ASSERT(value_ != NULL);
|
||||
try_index_(try_index) {
|
||||
ASSERT(value != NULL);
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(AssertBoolean)
|
||||
|
||||
intptr_t token_index() const { return token_index_; }
|
||||
intptr_t try_index() const { return try_index_; }
|
||||
Value* value() const { return value_; }
|
||||
Value* value() { return inputs_[0]; }
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
Value* value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AssertBooleanComp);
|
||||
};
|
||||
|
@ -242,7 +287,7 @@ class AssertBooleanComp : public Computation {
|
|||
|
||||
// Denotes the current context, normally held in a register. This is
|
||||
// a computation, not a value, because it's mutable.
|
||||
class CurrentContextComp : public Computation {
|
||||
class CurrentContextComp : public TemplateComputation<0> {
|
||||
public:
|
||||
CurrentContextComp() { }
|
||||
|
||||
|
@ -253,19 +298,18 @@ class CurrentContextComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class StoreContextComp : public Computation {
|
||||
class StoreContextComp : public TemplateComputation<1> {
|
||||
public:
|
||||
explicit StoreContextComp(Value* value) : value_(value) {
|
||||
ASSERT(value_ != NULL);
|
||||
explicit StoreContextComp(Value* value) {
|
||||
ASSERT(value != NULL);
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(StoreContext);
|
||||
|
||||
Value* value() const { return value_; }
|
||||
Value* value() { return inputs_[0]; }
|
||||
|
||||
private:
|
||||
Value* value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreContextComp);
|
||||
};
|
||||
|
||||
|
@ -293,6 +337,8 @@ class ClosureCallComp : public Computation {
|
|||
intptr_t ArgumentCount() const { return arguments_->length(); }
|
||||
Value* ArgumentAt(intptr_t index) const { return (*arguments_)[index]; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const ClosureCallNode& ast_node_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -332,6 +378,8 @@ class InstanceCallComp : public Computation {
|
|||
const Array& argument_names() const { return argument_names_; }
|
||||
intptr_t checked_argument_count() const { return checked_argument_count_; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -344,54 +392,52 @@ class InstanceCallComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class StrictCompareComp : public Computation {
|
||||
class StrictCompareComp : public TemplateComputation<2> {
|
||||
public:
|
||||
StrictCompareComp(Token::Kind kind, Value* left, Value* right)
|
||||
: kind_(kind), left_(left), right_(right) {
|
||||
: kind_(kind) {
|
||||
ASSERT((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kNE_STRICT));
|
||||
inputs_[0] = left;
|
||||
inputs_[1] = right;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(StrictCompare)
|
||||
|
||||
Token::Kind kind() const { return kind_; }
|
||||
Value* left() const { return left_; }
|
||||
Value* right() const { return right_; }
|
||||
Value* left() { return inputs_[0]; }
|
||||
Value* right() { return inputs_[1]; }
|
||||
|
||||
private:
|
||||
const Token::Kind kind_;
|
||||
Value* left_;
|
||||
Value* right_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StrictCompareComp);
|
||||
};
|
||||
|
||||
|
||||
class EqualityCompareComp : public Computation {
|
||||
class EqualityCompareComp : public TemplateComputation<2> {
|
||||
public:
|
||||
EqualityCompareComp(intptr_t token_index,
|
||||
intptr_t try_index,
|
||||
Value* left,
|
||||
Value* right)
|
||||
: token_index_(token_index),
|
||||
try_index_(try_index),
|
||||
left_(left),
|
||||
right_(right) {
|
||||
ASSERT(left_ != NULL);
|
||||
ASSERT(right_ != NULL);
|
||||
try_index_(try_index) {
|
||||
ASSERT(left != NULL);
|
||||
ASSERT(right != NULL);
|
||||
inputs_[0] = left;
|
||||
inputs_[1] = right;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(EqualityCompareComp)
|
||||
|
||||
intptr_t token_index() const { return token_index_; }
|
||||
intptr_t try_index() const { return try_index_; }
|
||||
Value* left() const { return left_; }
|
||||
Value* right() const { return right_; }
|
||||
Value* left() { return inputs_[0]; }
|
||||
Value* right() { return inputs_[1]; }
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
Value* left_;
|
||||
Value* right_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(EqualityCompareComp);
|
||||
};
|
||||
|
@ -424,6 +470,8 @@ class StaticCallComp : public Computation {
|
|||
intptr_t ArgumentCount() const { return arguments_->length(); }
|
||||
Value* ArgumentAt(intptr_t index) const { return (*arguments_)[index]; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -435,7 +483,7 @@ class StaticCallComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class LoadLocalComp : public Computation {
|
||||
class LoadLocalComp : public TemplateComputation<0> {
|
||||
public:
|
||||
LoadLocalComp(const LocalVariable& local, intptr_t context_level)
|
||||
: local_(local), context_level_(context_level) { }
|
||||
|
@ -453,29 +501,30 @@ class LoadLocalComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class StoreLocalComp : public Computation {
|
||||
class StoreLocalComp : public TemplateComputation<1> {
|
||||
public:
|
||||
StoreLocalComp(const LocalVariable& local,
|
||||
Value* value,
|
||||
intptr_t context_level)
|
||||
: local_(local), value_(value), context_level_(context_level) { }
|
||||
: local_(local), context_level_(context_level) {
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(StoreLocal)
|
||||
|
||||
const LocalVariable& local() const { return local_; }
|
||||
Value* value() const { return value_; }
|
||||
Value* value() { return inputs_[0]; }
|
||||
intptr_t context_level() const { return context_level_; }
|
||||
|
||||
private:
|
||||
const LocalVariable& local_;
|
||||
Value* value_;
|
||||
const intptr_t context_level_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreLocalComp);
|
||||
};
|
||||
|
||||
|
||||
class NativeCallComp : public Computation {
|
||||
class NativeCallComp : public TemplateComputation<0> {
|
||||
public:
|
||||
NativeCallComp(NativeBodyNode* node, intptr_t try_index)
|
||||
: ast_node_(*node), try_index_(try_index) {}
|
||||
|
@ -507,35 +556,37 @@ class NativeCallComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class LoadInstanceFieldComp : public Computation {
|
||||
class LoadInstanceFieldComp : public TemplateComputation<1> {
|
||||
public:
|
||||
LoadInstanceFieldComp(LoadInstanceFieldNode* ast_node, Value* instance)
|
||||
: ast_node_(*ast_node), instance_(instance) {
|
||||
ASSERT(instance_ != NULL);
|
||||
: ast_node_(*ast_node) {
|
||||
ASSERT(instance != NULL);
|
||||
inputs_[0] = instance;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(LoadInstanceField)
|
||||
|
||||
const Field& field() const { return ast_node_.field(); }
|
||||
|
||||
Value* instance() const { return instance_; }
|
||||
Value* instance() { return inputs_[0]; }
|
||||
|
||||
private:
|
||||
const LoadInstanceFieldNode& ast_node_;
|
||||
Value* instance_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LoadInstanceFieldComp);
|
||||
};
|
||||
|
||||
|
||||
class StoreInstanceFieldComp : public Computation {
|
||||
class StoreInstanceFieldComp : public TemplateComputation<2> {
|
||||
public:
|
||||
StoreInstanceFieldComp(StoreInstanceFieldNode* ast_node,
|
||||
Value* instance,
|
||||
Value* value)
|
||||
: ast_node_(*ast_node), instance_(instance), value_(value) {
|
||||
ASSERT(instance_ != NULL);
|
||||
ASSERT(value_ != NULL);
|
||||
: ast_node_(*ast_node) {
|
||||
ASSERT(instance != NULL);
|
||||
ASSERT(value != NULL);
|
||||
inputs_[0] = instance;
|
||||
inputs_[1] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(StoreInstanceField)
|
||||
|
@ -543,19 +594,17 @@ class StoreInstanceFieldComp : public Computation {
|
|||
intptr_t token_index() const { return ast_node_.token_index(); }
|
||||
const Field& field() const { return ast_node_.field(); }
|
||||
|
||||
Value* instance() const { return instance_; }
|
||||
Value* value() const { return value_; }
|
||||
Value* instance() { return inputs_[0]; }
|
||||
Value* value() { return inputs_[1]; }
|
||||
|
||||
private:
|
||||
const StoreInstanceFieldNode& ast_node_;
|
||||
Value* instance_;
|
||||
Value* value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldComp);
|
||||
};
|
||||
|
||||
|
||||
class LoadStaticFieldComp : public Computation {
|
||||
class LoadStaticFieldComp : public TemplateComputation<0> {
|
||||
public:
|
||||
explicit LoadStaticFieldComp(const Field& field) : field_(field) {}
|
||||
|
||||
|
@ -570,23 +619,22 @@ class LoadStaticFieldComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class StoreStaticFieldComp : public Computation {
|
||||
class StoreStaticFieldComp : public TemplateComputation<1> {
|
||||
public:
|
||||
StoreStaticFieldComp(const Field& field, Value* value)
|
||||
: field_(field),
|
||||
value_(value) {
|
||||
: field_(field) {
|
||||
ASSERT(field.IsZoneHandle());
|
||||
ASSERT(value != NULL);
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(StoreStaticField);
|
||||
|
||||
const Field& field() const { return field_; }
|
||||
Value* value() const { return value_; }
|
||||
Value* value() { return inputs_[0]; }
|
||||
|
||||
private:
|
||||
const Field& field_;
|
||||
Value* const value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreStaticFieldComp);
|
||||
};
|
||||
|
@ -594,7 +642,7 @@ class StoreStaticFieldComp : public Computation {
|
|||
|
||||
// Not simply an InstanceCall because it has somewhat more complicated
|
||||
// semantics: the value operand is preserved before the call.
|
||||
class StoreIndexedComp : public Computation {
|
||||
class StoreIndexedComp : public TemplateComputation<3> {
|
||||
public:
|
||||
StoreIndexedComp(intptr_t token_index,
|
||||
intptr_t try_index,
|
||||
|
@ -602,25 +650,23 @@ class StoreIndexedComp : public Computation {
|
|||
Value* index,
|
||||
Value* value)
|
||||
: token_index_(token_index),
|
||||
try_index_(try_index),
|
||||
array_(array),
|
||||
index_(index),
|
||||
value_(value) { }
|
||||
try_index_(try_index) {
|
||||
inputs_[0] = array;
|
||||
inputs_[1] = index;
|
||||
inputs_[2] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(StoreIndexed)
|
||||
|
||||
intptr_t token_index() const { return token_index_; }
|
||||
intptr_t try_index() const { return try_index_; }
|
||||
Value* array() const { return array_; }
|
||||
Value* index() const { return index_; }
|
||||
Value* value() const { return value_; }
|
||||
Value* array() { return inputs_[0]; }
|
||||
Value* index() { return inputs_[1]; }
|
||||
Value* value() { return inputs_[2]; }
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
Value* array_;
|
||||
Value* index_;
|
||||
Value* value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreIndexedComp);
|
||||
};
|
||||
|
@ -628,7 +674,7 @@ class StoreIndexedComp : public Computation {
|
|||
|
||||
// Not simply an InstanceCall because it has somewhat more complicated
|
||||
// semantics: the value operand is preserved before the call.
|
||||
class InstanceSetterComp : public Computation {
|
||||
class InstanceSetterComp : public TemplateComputation<2> {
|
||||
public:
|
||||
InstanceSetterComp(intptr_t token_index,
|
||||
intptr_t try_index,
|
||||
|
@ -637,24 +683,23 @@ class InstanceSetterComp : public Computation {
|
|||
Value* value)
|
||||
: token_index_(token_index),
|
||||
try_index_(try_index),
|
||||
field_name_(field_name),
|
||||
receiver_(receiver),
|
||||
value_(value) { }
|
||||
field_name_(field_name) {
|
||||
inputs_[0] = receiver;
|
||||
inputs_[1] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(InstanceSetter)
|
||||
|
||||
intptr_t token_index() const { return token_index_; }
|
||||
intptr_t try_index() const { return try_index_; }
|
||||
const String& field_name() const { return field_name_; }
|
||||
Value* receiver() const { return receiver_; }
|
||||
Value* value() const { return value_; }
|
||||
Value* receiver() { return inputs_[0]; }
|
||||
Value* value() { return inputs_[1]; }
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
const String& field_name_;
|
||||
Value* const receiver_;
|
||||
Value* const value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(InstanceSetterComp);
|
||||
};
|
||||
|
@ -662,7 +707,7 @@ class InstanceSetterComp : public Computation {
|
|||
|
||||
// Not simply a StaticCall because it has somewhat more complicated
|
||||
// semantics: the value operand is preserved before the call.
|
||||
class StaticSetterComp : public Computation {
|
||||
class StaticSetterComp : public TemplateComputation<1> {
|
||||
public:
|
||||
StaticSetterComp(intptr_t token_index,
|
||||
intptr_t try_index,
|
||||
|
@ -670,38 +715,38 @@ class StaticSetterComp : public Computation {
|
|||
Value* value)
|
||||
: token_index_(token_index),
|
||||
try_index_(try_index),
|
||||
setter_function_(setter_function),
|
||||
value_(value) { }
|
||||
setter_function_(setter_function) {
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(StaticSetter)
|
||||
|
||||
intptr_t token_index() const { return token_index_; }
|
||||
intptr_t try_index() const { return try_index_; }
|
||||
const Function& setter_function() const { return setter_function_; }
|
||||
Value* value() const { return value_; }
|
||||
Value* value() { return inputs_[0]; }
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
const Function& setter_function_;
|
||||
Value* const value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StaticSetterComp);
|
||||
};
|
||||
|
||||
|
||||
// Note overrideable, built-in: value? false : true.
|
||||
class BooleanNegateComp : public Computation {
|
||||
class BooleanNegateComp : public TemplateComputation<1> {
|
||||
public:
|
||||
explicit BooleanNegateComp(Value* value) : value_(value) {}
|
||||
explicit BooleanNegateComp(Value* value) {
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(BooleanNegate)
|
||||
|
||||
Value* value() const { return value_; }
|
||||
Value* value() { return inputs_[0]; }
|
||||
|
||||
private:
|
||||
Value* value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BooleanNegateComp);
|
||||
};
|
||||
|
||||
|
@ -733,6 +778,8 @@ class InstanceOfComp : public Computation {
|
|||
intptr_t token_index() const { return token_index_; }
|
||||
intptr_t try_index() const { return try_index_; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -762,6 +809,8 @@ class AllocateObjectComp : public Computation {
|
|||
intptr_t try_index() const { return try_index_; }
|
||||
const ZoneGrowableArray<Value*>& arguments() const { return *arguments_; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const ConstructorCallNode& ast_node_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -787,6 +836,8 @@ class AllocateObjectWithBoundsCheckComp : public Computation {
|
|||
intptr_t try_index() const { return try_index_; }
|
||||
const ZoneGrowableArray<Value*>& arguments() const { return *arguments_; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const ConstructorCallNode& ast_node_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -818,6 +869,8 @@ class CreateArrayComp : public Computation {
|
|||
intptr_t ElementCount() const { return elements_->length(); }
|
||||
Value* ElementAt(intptr_t i) const { return (*elements_)[i]; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const ArrayNode& ast_node_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -844,6 +897,8 @@ class CreateClosureComp : public Computation {
|
|||
const Function& function() const { return ast_node_.function(); }
|
||||
Value* type_arguments() const { return type_arguments_; }
|
||||
|
||||
virtual intptr_t InputCount() const;
|
||||
|
||||
private:
|
||||
const ClosureNode& ast_node_;
|
||||
const intptr_t try_index_;
|
||||
|
@ -853,40 +908,40 @@ class CreateClosureComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class NativeLoadFieldComp : public Computation {
|
||||
class NativeLoadFieldComp : public TemplateComputation<1> {
|
||||
public:
|
||||
NativeLoadFieldComp(Value* value, intptr_t offset_in_bytes)
|
||||
: value_(value), offset_in_bytes_(offset_in_bytes) {
|
||||
: offset_in_bytes_(offset_in_bytes) {
|
||||
ASSERT(value != NULL);
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(NativeLoadField)
|
||||
|
||||
Value* value() const { return value_; }
|
||||
Value* value() { return inputs_[0]; }
|
||||
intptr_t offset_in_bytes() const { return offset_in_bytes_; }
|
||||
|
||||
private:
|
||||
Value* value_;
|
||||
intptr_t offset_in_bytes_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeLoadFieldComp);
|
||||
};
|
||||
|
||||
|
||||
class ExtractFactoryTypeArgumentsComp : public Computation {
|
||||
class ExtractFactoryTypeArgumentsComp : public TemplateComputation<1> {
|
||||
public:
|
||||
ExtractFactoryTypeArgumentsComp(ConstructorCallNode* ast_node,
|
||||
intptr_t try_index,
|
||||
Value* instantiator)
|
||||
: ast_node_(*ast_node),
|
||||
try_index_(try_index),
|
||||
instantiator_(instantiator) {
|
||||
ASSERT(instantiator_ != NULL);
|
||||
try_index_(try_index) {
|
||||
ASSERT(instantiator != NULL);
|
||||
inputs_[0] = instantiator;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(ExtractFactoryTypeArguments)
|
||||
|
||||
Value* instantiator() const { return instantiator_; }
|
||||
Value* instantiator() { return inputs_[0]; }
|
||||
const AbstractTypeArguments& type_arguments() const {
|
||||
return ast_node_.type_arguments();
|
||||
}
|
||||
|
@ -897,23 +952,23 @@ class ExtractFactoryTypeArgumentsComp : public Computation {
|
|||
private:
|
||||
const ConstructorCallNode& ast_node_;
|
||||
const intptr_t try_index_;
|
||||
Value* instantiator_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ExtractFactoryTypeArgumentsComp);
|
||||
};
|
||||
|
||||
|
||||
class ExtractConstructorTypeArgumentsComp : public Computation {
|
||||
class ExtractConstructorTypeArgumentsComp : public TemplateComputation<1> {
|
||||
public:
|
||||
ExtractConstructorTypeArgumentsComp(ConstructorCallNode* ast_node,
|
||||
Value* instantiator)
|
||||
: ast_node_(*ast_node), instantiator_(instantiator) {
|
||||
ASSERT(instantiator_ != NULL);
|
||||
: ast_node_(*ast_node) {
|
||||
ASSERT(instantiator != NULL);
|
||||
inputs_[0] = instantiator;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(ExtractConstructorTypeArguments)
|
||||
|
||||
Value* instantiator() const { return instantiator_; }
|
||||
Value* instantiator() { return inputs_[0]; }
|
||||
const AbstractTypeArguments& type_arguments() const {
|
||||
return ast_node_.type_arguments();
|
||||
}
|
||||
|
@ -922,27 +977,26 @@ class ExtractConstructorTypeArgumentsComp : public Computation {
|
|||
|
||||
private:
|
||||
const ConstructorCallNode& ast_node_;
|
||||
Value* instantiator_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ExtractConstructorTypeArgumentsComp);
|
||||
};
|
||||
|
||||
|
||||
class ExtractConstructorInstantiatorComp : public Computation {
|
||||
class ExtractConstructorInstantiatorComp : public TemplateComputation<2> {
|
||||
public:
|
||||
ExtractConstructorInstantiatorComp(ConstructorCallNode* ast_node,
|
||||
Value* instantiator,
|
||||
Value* discard_value)
|
||||
: ast_node_(*ast_node),
|
||||
instantiator_(instantiator),
|
||||
discard_value_(discard_value) {
|
||||
ASSERT(instantiator_ != NULL);
|
||||
: ast_node_(*ast_node) {
|
||||
ASSERT(instantiator != NULL);
|
||||
inputs_[0] = instantiator;
|
||||
inputs_[1] = discard_value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(ExtractConstructorInstantiator)
|
||||
|
||||
Value* instantiator() const { return instantiator_; }
|
||||
Value* discard_value() const { return discard_value_; }
|
||||
Value* instantiator() { return inputs_[0]; }
|
||||
Value* discard_value() { return inputs_[1]; }
|
||||
const AbstractTypeArguments& type_arguments() const {
|
||||
return ast_node_.type_arguments();
|
||||
}
|
||||
|
@ -951,14 +1005,12 @@ class ExtractConstructorInstantiatorComp : public Computation {
|
|||
|
||||
private:
|
||||
const ConstructorCallNode& ast_node_;
|
||||
Value* instantiator_;
|
||||
Value* discard_value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ExtractConstructorInstantiatorComp);
|
||||
};
|
||||
|
||||
|
||||
class AllocateContextComp : public Computation {
|
||||
class AllocateContextComp : public TemplateComputation<0> {
|
||||
public:
|
||||
AllocateContextComp(intptr_t token_index,
|
||||
intptr_t try_index,
|
||||
|
@ -982,51 +1034,48 @@ class AllocateContextComp : public Computation {
|
|||
};
|
||||
|
||||
|
||||
class ChainContextComp : public Computation {
|
||||
class ChainContextComp : public TemplateComputation<1> {
|
||||
public:
|
||||
explicit ChainContextComp(Value* context_value)
|
||||
: context_value_(context_value) {
|
||||
ASSERT(context_value_ != NULL);
|
||||
explicit ChainContextComp(Value* context_value) {
|
||||
ASSERT(context_value != NULL);
|
||||
inputs_[0] = context_value;
|
||||
}
|
||||
|
||||
DECLARE_COMPUTATION(ChainContext)
|
||||
|
||||
Value* context_value() const { return context_value_; }
|
||||
Value* context_value() { return inputs_[0]; }
|
||||
|
||||
private:
|
||||
Value* context_value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ChainContextComp);
|
||||
};
|
||||
|
||||
|
||||
class CloneContextComp : public Computation {
|
||||
class CloneContextComp : public TemplateComputation<1> {
|
||||
public:
|
||||
CloneContextComp(intptr_t token_index,
|
||||
intptr_t try_index,
|
||||
Value* context_value)
|
||||
: token_index_(token_index),
|
||||
try_index_(try_index),
|
||||
context_value_(context_value) {
|
||||
ASSERT(context_value_ != NULL);
|
||||
try_index_(try_index) {
|
||||
ASSERT(context_value != NULL);
|
||||
inputs_[0] = context_value;
|
||||
}
|
||||
|
||||
intptr_t token_index() const { return token_index_; }
|
||||
intptr_t try_index() const { return try_index_; }
|
||||
Value* context_value() const { return context_value_; }
|
||||
Value* context_value() { return inputs_[0]; }
|
||||
|
||||
DECLARE_COMPUTATION(CloneContext)
|
||||
|
||||
private:
|
||||
const intptr_t token_index_;
|
||||
const intptr_t try_index_;
|
||||
Value* context_value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CloneContextComp);
|
||||
};
|
||||
|
||||
|
||||
class CatchEntryComp : public Computation {
|
||||
class CatchEntryComp : public TemplateComputation<0> {
|
||||
public:
|
||||
CatchEntryComp(const LocalVariable& exception_var,
|
||||
const LocalVariable& stacktrace_var)
|
||||
|
@ -1087,6 +1136,7 @@ FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
|
|||
virtual Instruction* Accept(FlowGraphVisitor* visitor); \
|
||||
virtual bool Is##type() const { return true; } \
|
||||
virtual type##Instr* As##type() { return this; } \
|
||||
virtual intptr_t InputCount() const; \
|
||||
|
||||
|
||||
class Instruction : public ZoneAllocated {
|
||||
|
@ -1101,6 +1151,12 @@ class Instruction : public ZoneAllocated {
|
|||
BlockEntryInstr* AsBlockEntry() {
|
||||
return IsBlockEntry() ? reinterpret_cast<BlockEntryInstr*>(this) : NULL;
|
||||
}
|
||||
virtual bool IsDefinition() const { return false; }
|
||||
Definition* AsDefinition() {
|
||||
return IsDefinition() ? reinterpret_cast<Definition*>(this) : NULL;
|
||||
}
|
||||
|
||||
virtual intptr_t InputCount() const = 0;
|
||||
|
||||
// Visiting support.
|
||||
virtual Instruction* Accept(FlowGraphVisitor* visitor) = 0;
|
||||
|
@ -1300,12 +1356,15 @@ class DoInstr : public Instruction {
|
|||
|
||||
class Definition : public Instruction {
|
||||
public:
|
||||
explicit Definition(intptr_t temp_index) : temp_index_(temp_index) { }
|
||||
Definition() : temp_index_(-1) { }
|
||||
|
||||
virtual bool IsDefinition() const { return true; }
|
||||
|
||||
intptr_t temp_index() const { return temp_index_; }
|
||||
void set_temp_index(intptr_t index) { temp_index_ = index; }
|
||||
|
||||
private:
|
||||
const intptr_t temp_index_;
|
||||
intptr_t temp_index_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Definition);
|
||||
};
|
||||
|
@ -1313,8 +1372,8 @@ class Definition : public Instruction {
|
|||
|
||||
class BindInstr : public Definition {
|
||||
public:
|
||||
BindInstr(intptr_t temp_index, Computation* computation)
|
||||
: Definition(temp_index), computation_(computation), successor_(NULL) { }
|
||||
explicit BindInstr(Computation* computation)
|
||||
: Definition(), computation_(computation), successor_(NULL) { }
|
||||
|
||||
DECLARE_INSTRUCTION(Bind)
|
||||
|
||||
|
@ -1345,8 +1404,8 @@ class BindInstr : public Definition {
|
|||
// (named 'source') without counting as the use of the source.
|
||||
class PickTempInstr : public Definition {
|
||||
public:
|
||||
PickTempInstr(intptr_t temp_index, intptr_t source)
|
||||
: Definition(temp_index), source_(source), successor_(NULL) { }
|
||||
explicit PickTempInstr(intptr_t source)
|
||||
: Definition(), source_(source), successor_(NULL) { }
|
||||
|
||||
DECLARE_INSTRUCTION(PickTemp)
|
||||
|
||||
|
|
Loading…
Reference in a new issue