Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "vm/intermediate_language.h"
|
|
|
|
|
2012-05-16 13:28:02 +00:00
|
|
|
#include "vm/bit_vector.h"
|
2012-06-26 17:43:44 +00:00
|
|
|
#include "vm/dart_entry.h"
|
2012-08-07 15:53:02 +00:00
|
|
|
#include "vm/flow_graph_allocator.h"
|
2012-05-18 01:04:56 +00:00
|
|
|
#include "vm/flow_graph_builder.h"
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
#include "vm/flow_graph_compiler.h"
|
|
|
|
#include "vm/locations.h"
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
#include "vm/object.h"
|
2012-08-11 00:09:12 +00:00
|
|
|
#include "vm/object_store.h"
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
#include "vm/os.h"
|
|
|
|
#include "vm/scopes.h"
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
#include "vm/stub_code.h"
|
2012-07-24 00:01:50 +00:00
|
|
|
#include "vm/symbols.h"
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
2012-07-26 16:04:36 +00:00
|
|
|
DECLARE_FLAG(bool, enable_type_checks);
|
|
|
|
|
2012-08-20 12:40:14 +00:00
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t Definition::Hashcode() const {
|
|
|
|
intptr_t result = tag();
|
2012-08-20 12:40:14 +00:00
|
|
|
for (intptr_t i = 0; i < InputCount(); ++i) {
|
2012-08-30 09:08:27 +00:00
|
|
|
Value* value = InputAt(i);
|
|
|
|
intptr_t j = value->definition()->ssa_temp_index();
|
2012-08-20 12:40:14 +00:00
|
|
|
result = result * 31 + j;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
bool Definition::Equals(Definition* other) const {
|
|
|
|
if (tag() != other->tag()) return false;
|
2012-08-20 12:40:14 +00:00
|
|
|
for (intptr_t i = 0; i < InputCount(); ++i) {
|
|
|
|
if (!InputAt(i)->Equals(other->InputAt(i))) return false;
|
|
|
|
}
|
|
|
|
return AttributesEqual(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-30 09:08:27 +00:00
|
|
|
bool Value::Equals(Value* other) const {
|
|
|
|
return definition() == other->definition();
|
2012-08-21 13:07:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
bool CheckClassInstr::AttributesEqual(Definition* other) const {
|
|
|
|
CheckClassInstr* other_check = other->AsCheckClass();
|
|
|
|
ASSERT(other_check != NULL);
|
2012-09-03 11:27:09 +00:00
|
|
|
if (unary_checks().NumberOfChecks() !=
|
|
|
|
other_check->unary_checks().NumberOfChecks()) {
|
2012-08-20 12:40:14 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-09-03 11:27:09 +00:00
|
|
|
for (intptr_t i = 0; i < unary_checks().NumberOfChecks(); ++i) {
|
2012-08-20 12:40:14 +00:00
|
|
|
// TODO(fschneider): Make sure ic_data are sorted to hit more cases.
|
2012-09-03 11:27:09 +00:00
|
|
|
if (unary_checks().GetReceiverClassIdAt(i) !=
|
|
|
|
other_check->unary_checks().GetReceiverClassIdAt(i)) {
|
2012-08-20 12:40:14 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
bool CheckArrayBoundInstr::AttributesEqual(Definition* other) const {
|
|
|
|
CheckArrayBoundInstr* other_check = other->AsCheckArrayBound();
|
|
|
|
ASSERT(other_check != NULL);
|
2012-08-28 09:14:57 +00:00
|
|
|
return array_type() == other_check->array_type();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-12 08:45:02 +00:00
|
|
|
bool LoadVMFieldInstr::AttributesEqual(Definition* other) const {
|
|
|
|
LoadVMFieldInstr* other_load = other->AsLoadVMField();
|
|
|
|
ASSERT(other_load != NULL);
|
|
|
|
ASSERT((offset_in_bytes() != other_load->offset_in_bytes()) ||
|
|
|
|
((immutable_ == other_load->immutable_) &&
|
|
|
|
(ResultCid() == other_load->ResultCid())));
|
|
|
|
return offset_in_bytes() == other_load->offset_in_bytes();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-15 23:49:12 +00:00
|
|
|
// Returns true if the value represents a constant.
|
2012-08-30 09:08:27 +00:00
|
|
|
bool Value::BindsToConstant() const {
|
2012-09-05 17:04:49 +00:00
|
|
|
return definition()->IsConstant();
|
2012-08-15 23:49:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Returns true if the value represents constant null.
|
2012-08-30 09:08:27 +00:00
|
|
|
bool Value::BindsToConstantNull() const {
|
2012-09-05 17:04:49 +00:00
|
|
|
ConstantInstr* constant = definition()->AsConstant();
|
2012-08-29 12:56:57 +00:00
|
|
|
return (constant != NULL) && constant->value().IsNull();
|
2012-08-15 23:49:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-30 09:08:27 +00:00
|
|
|
const Object& Value::BoundConstant() const {
|
2012-08-16 22:22:57 +00:00
|
|
|
ASSERT(BindsToConstant());
|
2012-09-05 17:04:49 +00:00
|
|
|
ConstantInstr* constant = definition()->AsConstant();
|
2012-08-16 22:22:57 +00:00
|
|
|
ASSERT(constant != NULL);
|
2012-08-29 12:56:57 +00:00
|
|
|
return constant->value();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
bool ConstantInstr::AttributesEqual(Definition* other) const {
|
|
|
|
ConstantInstr* other_constant = other->AsConstant();
|
|
|
|
ASSERT(other_constant != NULL);
|
|
|
|
return (value().raw() == other_constant->value().raw());
|
2012-08-29 12:56:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GraphEntryInstr::GraphEntryInstr(TargetEntryInstr* normal_entry)
|
2012-08-29 16:44:18 +00:00
|
|
|
: BlockEntryInstr(CatchClauseNode::kInvalidTryIndex),
|
2012-08-29 12:56:57 +00:00
|
|
|
normal_entry_(normal_entry),
|
|
|
|
catch_entries_(),
|
|
|
|
start_env_(NULL),
|
2012-09-07 11:05:02 +00:00
|
|
|
constant_null_(NULL),
|
2012-08-29 12:56:57 +00:00
|
|
|
spill_slot_count_(0) {
|
2012-08-16 22:22:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-15 00:56:25 +00:00
|
|
|
MethodRecognizer::Kind MethodRecognizer::RecognizeKind(
|
|
|
|
const Function& function) {
|
2012-08-23 01:10:47 +00:00
|
|
|
// Only core and math library methods can be recognized.
|
2012-06-15 00:56:25 +00:00
|
|
|
const Library& core_lib = Library::Handle(Library::CoreLibrary());
|
|
|
|
const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
|
2012-08-23 01:10:47 +00:00
|
|
|
const Library& math_lib = Library::Handle(Library::MathLibrary());
|
2012-08-14 00:38:01 +00:00
|
|
|
const Class& function_class = Class::Handle(function.Owner());
|
2012-06-15 00:56:25 +00:00
|
|
|
if ((function_class.library() != core_lib.raw()) &&
|
2012-08-23 01:10:47 +00:00
|
|
|
(function_class.library() != core_impl_lib.raw()) &&
|
|
|
|
(function_class.library() != math_lib.raw())) {
|
2012-06-15 00:56:25 +00:00
|
|
|
return kUnknown;
|
|
|
|
}
|
|
|
|
const String& recognize_name = String::Handle(function.name());
|
|
|
|
const String& recognize_class = String::Handle(function_class.Name());
|
|
|
|
String& test_function_name = String::Handle();
|
|
|
|
String& test_class_name = String::Handle();
|
|
|
|
#define RECOGNIZE_FUNCTION(class_name, function_name, enum_name) \
|
2012-07-24 00:01:50 +00:00
|
|
|
test_function_name = Symbols::New(#function_name); \
|
|
|
|
test_class_name = Symbols::New(#class_name); \
|
2012-06-15 00:56:25 +00:00
|
|
|
if (recognize_name.Equals(test_function_name) && \
|
|
|
|
recognize_class.Equals(test_class_name)) { \
|
|
|
|
return k##enum_name; \
|
|
|
|
}
|
|
|
|
RECOGNIZED_LIST(RECOGNIZE_FUNCTION)
|
|
|
|
#undef RECOGNIZE_FUNCTION
|
|
|
|
return kUnknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* MethodRecognizer::KindToCString(Kind kind) {
|
|
|
|
#define KIND_TO_STRING(class_name, function_name, enum_name) \
|
|
|
|
if (kind == k##enum_name) return #enum_name;
|
|
|
|
RECOGNIZED_LIST(KIND_TO_STRING)
|
|
|
|
#undef KIND_TO_STRING
|
|
|
|
return "?";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-28 08:58:49 +00:00
|
|
|
// ==== Support for visiting flow graphs.
|
2012-05-15 08:55:56 +00:00
|
|
|
#define DEFINE_ACCEPT(ShortName) \
|
2012-07-09 12:58:36 +00:00
|
|
|
void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \
|
2012-05-15 08:55:56 +00:00
|
|
|
visitor->Visit##ShortName(this); \
|
2012-02-23 18:29:58 +00:00
|
|
|
}
|
|
|
|
|
2012-05-15 08:55:56 +00:00
|
|
|
FOR_EACH_INSTRUCTION(DEFINE_ACCEPT)
|
2012-02-23 18:29:58 +00:00
|
|
|
|
2012-05-15 08:55:56 +00:00
|
|
|
#undef DEFINE_ACCEPT
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
|
|
|
|
|
2012-07-30 13:26:31 +00:00
|
|
|
Instruction* Instruction::RemoveFromGraph(bool return_previous) {
|
|
|
|
ASSERT(!IsBlockEntry());
|
2012-08-27 09:30:20 +00:00
|
|
|
ASSERT(!IsControl());
|
2012-07-30 13:26:31 +00:00
|
|
|
ASSERT(!IsThrow());
|
|
|
|
ASSERT(!IsReturn());
|
|
|
|
ASSERT(!IsReThrow());
|
|
|
|
ASSERT(!IsGoto());
|
|
|
|
ASSERT(previous() != NULL);
|
|
|
|
Instruction* prev_instr = previous();
|
|
|
|
Instruction* next_instr = next();
|
|
|
|
ASSERT(next_instr != NULL);
|
|
|
|
ASSERT(!next_instr->IsBlockEntry());
|
|
|
|
prev_instr->set_next(next_instr);
|
|
|
|
next_instr->set_previous(prev_instr);
|
2012-07-09 20:31:25 +00:00
|
|
|
// Reset successor and previous instruction to indicate
|
|
|
|
// that the instruction is removed from the graph.
|
2012-07-30 13:26:31 +00:00
|
|
|
set_previous(NULL);
|
|
|
|
set_next(NULL);
|
|
|
|
return return_previous ? prev_instr : next_instr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-03 14:35:02 +00:00
|
|
|
void Definition::InsertBefore(Instruction* next) {
|
2012-08-20 12:40:14 +00:00
|
|
|
ASSERT(previous_ == NULL);
|
|
|
|
ASSERT(next_ == NULL);
|
|
|
|
next_ = next;
|
|
|
|
previous_ = next->previous_;
|
|
|
|
next->previous_ = this;
|
|
|
|
previous_->next_ = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-03 14:35:02 +00:00
|
|
|
void Definition::InsertAfter(Instruction* prev) {
|
2012-08-24 14:45:42 +00:00
|
|
|
ASSERT(previous_ == NULL);
|
|
|
|
ASSERT(next_ == NULL);
|
|
|
|
previous_ = prev;
|
|
|
|
next_ = prev->next_;
|
|
|
|
next_->previous_ = this;
|
|
|
|
previous_->next_ = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-06 13:21:20 +00:00
|
|
|
BlockEntryInstr* Definition::GetBlock() const {
|
|
|
|
// TODO(fschneider): Implement a faster way to get the block of an
|
|
|
|
// instruction.
|
|
|
|
ASSERT(previous() != NULL);
|
|
|
|
Instruction* result = previous();
|
|
|
|
while (!result->IsBlockEntry()) result = result->previous();
|
|
|
|
return result->AsBlockEntry();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void ForwardInstructionIterator::RemoveCurrentFromGraph() {
|
|
|
|
current_ = current_->RemoveFromGraph(true); // Set current_ to previous.
|
2012-09-04 09:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void ForwardInstructionIterator::ReplaceCurrentWith(Definition* other) {
|
|
|
|
Definition* defn = current_->AsDefinition();
|
|
|
|
ASSERT(defn != NULL);
|
|
|
|
defn->ReplaceUsesWith(other);
|
|
|
|
ASSERT(other->env() == NULL);
|
|
|
|
other->set_env(defn->env());
|
|
|
|
defn->set_env(NULL);
|
|
|
|
ASSERT(!other->HasSSATemp());
|
|
|
|
if (defn->HasSSATemp()) other->set_ssa_temp_index(defn->ssa_temp_index());
|
|
|
|
|
|
|
|
other->InsertBefore(current_); // So other will be current.
|
|
|
|
RemoveCurrentFromGraph();
|
2012-07-09 20:31:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-23 18:29:58 +00:00
|
|
|
// Default implementation of visiting basic blocks. Can be overridden.
|
2012-03-16 22:20:04 +00:00
|
|
|
void FlowGraphVisitor::VisitBlocks() {
|
2012-08-15 23:49:12 +00:00
|
|
|
ASSERT(current_iterator_ == NULL);
|
2012-03-16 22:20:04 +00:00
|
|
|
for (intptr_t i = 0; i < block_order_.length(); ++i) {
|
2012-07-09 12:58:36 +00:00
|
|
|
BlockEntryInstr* entry = block_order_[i];
|
|
|
|
entry->Accept(this);
|
2012-08-15 23:49:12 +00:00
|
|
|
ForwardInstructionIterator it(entry);
|
|
|
|
current_iterator_ = ⁢
|
|
|
|
for (; !it.Done(); it.Advance()) {
|
2012-07-09 12:58:36 +00:00
|
|
|
it.Current()->Accept(this);
|
2012-02-23 18:29:58 +00:00
|
|
|
}
|
2012-08-15 23:49:12 +00:00
|
|
|
current_iterator_ = NULL;
|
2012-02-23 18:29:58 +00:00
|
|
|
}
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-10 01:26:13 +00:00
|
|
|
// Returns true if the compile type of this value is more specific than the
|
2012-08-01 17:15:55 +00:00
|
|
|
// given dst_type.
|
2012-08-10 01:26:13 +00:00
|
|
|
// TODO(regis): Support a set of compile types for the given value.
|
|
|
|
bool Value::CompileTypeIsMoreSpecificThan(const AbstractType& dst_type) const {
|
2012-08-15 23:49:12 +00:00
|
|
|
// No type is more specific than a malformed type.
|
|
|
|
if (dst_type.IsMalformed()) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-01 17:15:55 +00:00
|
|
|
|
|
|
|
// If the value is the null constant, its type (NullType) is more specific
|
|
|
|
// than the destination type, even if the destination type is the void type,
|
|
|
|
// since a void function is allowed to return null.
|
2012-08-15 23:49:12 +00:00
|
|
|
if (BindsToConstantNull()) {
|
2012-08-01 17:15:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Functions that do not explicitly return a value, implicitly return null,
|
|
|
|
// except generative constructors, which return the object being constructed.
|
|
|
|
// It is therefore acceptable for void functions to return null.
|
|
|
|
// In case of a null constant, we have already returned true above, else we
|
|
|
|
// return false here.
|
|
|
|
if (dst_type.IsVoidType()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-10 01:26:13 +00:00
|
|
|
// Consider the compile type of the value.
|
|
|
|
const AbstractType& compile_type = AbstractType::Handle(CompileType());
|
|
|
|
ASSERT(!compile_type.IsMalformed());
|
2012-08-01 17:15:55 +00:00
|
|
|
|
2012-08-10 01:26:13 +00:00
|
|
|
// If the compile type of the value is void, we are type checking the result
|
|
|
|
// of a void function, which was checked to be null at the return statement
|
2012-08-01 17:15:55 +00:00
|
|
|
// inside the function.
|
2012-08-10 01:26:13 +00:00
|
|
|
if (compile_type.IsVoidType()) {
|
2012-08-01 17:15:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-10 01:26:13 +00:00
|
|
|
// If the compile type of the value is NullType, the type test is eliminated.
|
2012-08-01 17:15:55 +00:00
|
|
|
// There are only three instances that can be of Class Null:
|
|
|
|
// Object::null(), Object::sentinel(), and Object::transition_sentinel().
|
|
|
|
// The inline code and run time code performing the type check will never
|
|
|
|
// encounter the 2 sentinel values. The type check of a sentinel value
|
|
|
|
// will always be eliminated here, because these sentinel values can only
|
|
|
|
// be encountered as constants, never as actual value of a heap object
|
|
|
|
// being type checked.
|
2012-08-10 01:26:13 +00:00
|
|
|
if (compile_type.IsNullType()) {
|
2012-08-01 17:15:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The run time type of the value is guaranteed to be a subtype of the
|
2012-08-10 01:26:13 +00:00
|
|
|
// compile time type of the value. However, establishing here that
|
|
|
|
// the compile time type is a subtype of the destination type does not
|
|
|
|
// guarantee that the run time type will also be a subtype of the destination
|
|
|
|
// type, because the subtype relation is not transitive.
|
2012-08-01 17:15:55 +00:00
|
|
|
// However, the 'more specific than' relation is transitive and is used
|
2012-08-10 01:26:13 +00:00
|
|
|
// here. In other words, if the compile type of the value is more specific
|
2012-08-01 17:15:55 +00:00
|
|
|
// than the destination type, the run time type of the value, which is
|
2012-08-10 01:26:13 +00:00
|
|
|
// guaranteed to be a subtype of the compile type, is also guaranteed to be
|
2012-08-01 17:15:55 +00:00
|
|
|
// a subtype of the destination type and the type check can therefore be
|
|
|
|
// eliminated.
|
2012-08-10 01:26:13 +00:00
|
|
|
return compile_type.IsMoreSpecificThan(dst_type, NULL);
|
2012-08-01 17:15:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-25 00:27:07 +00:00
|
|
|
bool Value::NeedsStoreBuffer() const {
|
|
|
|
const intptr_t cid = ResultCid();
|
|
|
|
if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !BindsToConstant();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-10 01:26:13 +00:00
|
|
|
RawAbstractType* PhiInstr::CompileType() const {
|
2012-08-13 16:56:10 +00:00
|
|
|
ASSERT(!HasPropagatedType());
|
|
|
|
// Since type propagation has not yet occured, we are reaching this phi via a
|
2012-08-10 01:26:13 +00:00
|
|
|
// back edge phi input. Return null as compile type so that this input is
|
|
|
|
// ignored in the first iteration of type propagation.
|
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RawAbstractType* PhiInstr::LeastSpecificInputType() const {
|
|
|
|
AbstractType& least_specific_type = AbstractType::Handle();
|
2012-08-01 17:15:55 +00:00
|
|
|
AbstractType& input_type = AbstractType::Handle();
|
2012-08-10 01:26:13 +00:00
|
|
|
for (intptr_t i = 0; i < InputCount(); i++) {
|
|
|
|
input_type = InputAt(i)->CompileType();
|
|
|
|
if (input_type.IsNull()) {
|
|
|
|
// This input is on a back edge and we are in the first iteration of type
|
|
|
|
// propagation. Ignore it.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ASSERT(!input_type.IsNull());
|
|
|
|
if (least_specific_type.IsNull() ||
|
|
|
|
least_specific_type.IsMoreSpecificThan(input_type, NULL)) {
|
2012-08-01 17:15:55 +00:00
|
|
|
// Type input_type is less specific than the current least_specific_type.
|
|
|
|
least_specific_type = input_type.raw();
|
2012-08-10 01:26:13 +00:00
|
|
|
} else if (input_type.IsMoreSpecificThan(least_specific_type, NULL)) {
|
|
|
|
// Type least_specific_type is less specific than input_type. No change.
|
2012-08-01 17:15:55 +00:00
|
|
|
} else {
|
|
|
|
// The types are unrelated. No need to continue.
|
|
|
|
least_specific_type = Type::ObjectType();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return least_specific_type.raw();
|
2012-07-26 16:04:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-10 01:26:13 +00:00
|
|
|
RawAbstractType* ParameterInstr::CompileType() const {
|
2012-08-13 16:56:10 +00:00
|
|
|
ASSERT(!HasPropagatedType());
|
2012-08-10 01:26:13 +00:00
|
|
|
// Note that returning the declared type of the formal parameter would be
|
|
|
|
// incorrect, because ParameterInstr is used as input to the type check
|
|
|
|
// verifying the run time type of the passed-in parameter and this check would
|
|
|
|
// always be wrongly eliminated.
|
2012-07-26 16:04:36 +00:00
|
|
|
return Type::DynamicType();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-10 14:28:02 +00:00
|
|
|
RawAbstractType* PushArgumentInstr::CompileType() const {
|
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-20 23:42:23 +00:00
|
|
|
intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const {
|
|
|
|
for (intptr_t i = 0; i < predecessors_.length(); ++i) {
|
|
|
|
if (predecessors_[i] == pred) return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-16 13:28:02 +00:00
|
|
|
// ==== Recording assigned variables.
|
2012-09-05 17:04:49 +00:00
|
|
|
void Definition::RecordAssignedVars(BitVector* assigned_vars,
|
|
|
|
intptr_t fixed_parameter_count) {
|
2012-05-16 13:28:02 +00:00
|
|
|
// Nothing to do for the base class.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars,
|
|
|
|
intptr_t fixed_parameter_count) {
|
2012-05-16 13:28:02 +00:00
|
|
|
if (!local().is_captured()) {
|
2012-07-26 13:21:39 +00:00
|
|
|
assigned_vars->Add(local().BitIndexIn(fixed_parameter_count));
|
2012-05-16 13:28:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-26 13:21:39 +00:00
|
|
|
void Instruction::RecordAssignedVars(BitVector* assigned_vars,
|
|
|
|
intptr_t fixed_parameter_count) {
|
2012-05-16 13:28:02 +00:00
|
|
|
// Nothing to do for the base class.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-30 09:08:27 +00:00
|
|
|
void Value::AddToInputUseList() {
|
2012-08-23 16:23:05 +00:00
|
|
|
set_next_use(definition()->input_use_list());
|
|
|
|
definition()->set_input_use_list(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-30 09:08:27 +00:00
|
|
|
void Value::AddToEnvUseList() {
|
2012-08-23 16:23:05 +00:00
|
|
|
set_next_use(definition()->env_use_list());
|
|
|
|
definition()->set_env_use_list(this);
|
|
|
|
}
|
2012-08-13 13:10:00 +00:00
|
|
|
|
2012-08-23 16:23:05 +00:00
|
|
|
|
|
|
|
void Definition::ReplaceUsesWith(Definition* other) {
|
|
|
|
ASSERT(other != NULL);
|
2012-08-27 12:17:47 +00:00
|
|
|
ASSERT(this != other);
|
2012-08-23 16:23:05 +00:00
|
|
|
while (input_use_list_ != NULL) {
|
2012-08-30 09:08:27 +00:00
|
|
|
Value* current = input_use_list_;
|
2012-08-23 16:23:05 +00:00
|
|
|
input_use_list_ = input_use_list_->next_use();
|
|
|
|
current->set_definition(other);
|
|
|
|
current->AddToInputUseList();
|
2012-08-13 13:10:00 +00:00
|
|
|
}
|
2012-08-23 16:23:05 +00:00
|
|
|
while (env_use_list_ != NULL) {
|
2012-08-30 09:08:27 +00:00
|
|
|
Value* current = env_use_list_;
|
2012-08-23 16:23:05 +00:00
|
|
|
env_use_list_ = env_use_list_->next_use();
|
|
|
|
current->set_definition(other);
|
|
|
|
current->AddToEnvUseList();
|
|
|
|
}
|
|
|
|
}
|
2012-08-13 13:10:00 +00:00
|
|
|
|
2012-08-23 16:23:05 +00:00
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void Definition::ReplaceWith(Definition* other,
|
|
|
|
ForwardInstructionIterator* iterator) {
|
2012-09-06 08:40:07 +00:00
|
|
|
if ((iterator != NULL) && (this == iterator->Current())) {
|
2012-09-05 17:04:49 +00:00
|
|
|
iterator->ReplaceCurrentWith(other);
|
|
|
|
} else {
|
|
|
|
ReplaceUsesWith(other);
|
|
|
|
ASSERT(other->env() == NULL);
|
|
|
|
other->set_env(env());
|
|
|
|
set_env(NULL);
|
|
|
|
ASSERT(!other->HasSSATemp());
|
|
|
|
if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index());
|
|
|
|
|
|
|
|
other->set_previous(previous());
|
|
|
|
previous()->set_next(other);
|
|
|
|
set_previous(NULL);
|
|
|
|
|
|
|
|
other->set_next(next());
|
|
|
|
next()->set_previous(other);
|
|
|
|
set_next(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-16 17:39:37 +00:00
|
|
|
bool Definition::SetPropagatedCid(intptr_t cid) {
|
2012-08-24 21:48:57 +00:00
|
|
|
if (cid == kIllegalCid) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-16 17:39:37 +00:00
|
|
|
if (propagated_cid_ == kIllegalCid) {
|
|
|
|
// First setting, nothing has changed.
|
|
|
|
propagated_cid_ = cid;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool has_changed = (propagated_cid_ != cid);
|
|
|
|
propagated_cid_ = cid;
|
|
|
|
return has_changed;
|
|
|
|
}
|
|
|
|
|
2012-08-10 01:26:13 +00:00
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t Definition::GetPropagatedCid() {
|
2012-08-16 17:39:37 +00:00
|
|
|
if (has_propagated_cid()) return propagated_cid();
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t cid = ResultCid();
|
2012-08-16 17:39:37 +00:00
|
|
|
ASSERT(cid != kIllegalCid);
|
|
|
|
SetPropagatedCid(cid);
|
|
|
|
return cid;
|
|
|
|
}
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
|
|
|
|
intptr_t PhiInstr::GetPropagatedCid() {
|
|
|
|
return propagated_cid();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
intptr_t ParameterInstr::GetPropagatedCid() {
|
|
|
|
return propagated_cid();
|
2012-05-16 13:28:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-23 18:29:58 +00:00
|
|
|
// ==== Postorder graph traversal.
|
2012-05-16 12:10:02 +00:00
|
|
|
void GraphEntryInstr::DiscoverBlocks(
|
|
|
|
BlockEntryInstr* current_block,
|
|
|
|
GrowableArray<BlockEntryInstr*>* preorder,
|
|
|
|
GrowableArray<BlockEntryInstr*>* postorder,
|
2012-05-16 13:28:02 +00:00
|
|
|
GrowableArray<intptr_t>* parent,
|
|
|
|
GrowableArray<BitVector*>* assigned_vars,
|
2012-07-26 13:21:39 +00:00
|
|
|
intptr_t variable_count,
|
|
|
|
intptr_t fixed_parameter_count) {
|
2012-05-16 12:10:02 +00:00
|
|
|
// We only visit this block once, first of all blocks.
|
|
|
|
ASSERT(preorder_number() == -1);
|
|
|
|
ASSERT(current_block == NULL);
|
|
|
|
ASSERT(preorder->is_empty());
|
|
|
|
ASSERT(postorder->is_empty());
|
|
|
|
ASSERT(parent->is_empty());
|
|
|
|
|
|
|
|
// This node has no parent, indicated by -1. The preorder number is 0.
|
|
|
|
parent->Add(-1);
|
|
|
|
set_preorder_number(0);
|
|
|
|
preorder->Add(this);
|
2012-05-16 13:28:02 +00:00
|
|
|
BitVector* vars =
|
|
|
|
(variable_count == 0) ? NULL : new BitVector(variable_count);
|
|
|
|
assigned_vars->Add(vars);
|
2012-05-16 12:10:02 +00:00
|
|
|
|
2012-06-06 11:09:02 +00:00
|
|
|
// The graph entry consists of only one instruction.
|
|
|
|
set_last_instruction(this);
|
|
|
|
|
2012-05-16 12:10:02 +00:00
|
|
|
// Iteratively traverse all successors. In the unoptimized code, we will
|
|
|
|
// enter the function at the first successor in reverse postorder, so we
|
|
|
|
// must visit the normal entry last.
|
|
|
|
for (intptr_t i = catch_entries_.length() - 1; i >= 0; --i) {
|
2012-05-18 01:04:56 +00:00
|
|
|
catch_entries_[i]->DiscoverBlocks(this, preorder, postorder,
|
2012-07-26 13:21:39 +00:00
|
|
|
parent, assigned_vars,
|
|
|
|
variable_count, fixed_parameter_count);
|
2012-05-16 12:10:02 +00:00
|
|
|
}
|
2012-05-18 01:04:56 +00:00
|
|
|
normal_entry_->DiscoverBlocks(this, preorder, postorder,
|
2012-07-26 13:21:39 +00:00
|
|
|
parent, assigned_vars,
|
|
|
|
variable_count, fixed_parameter_count);
|
2012-05-16 12:10:02 +00:00
|
|
|
|
|
|
|
// Assign postorder number.
|
|
|
|
set_postorder_number(postorder->length());
|
|
|
|
postorder->Add(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-16 13:28:02 +00:00
|
|
|
// Base class implementation used for JoinEntry and TargetEntry.
|
|
|
|
void BlockEntryInstr::DiscoverBlocks(
|
2012-03-19 19:39:14 +00:00
|
|
|
BlockEntryInstr* current_block,
|
2012-03-16 22:20:04 +00:00
|
|
|
GrowableArray<BlockEntryInstr*>* preorder,
|
2012-03-19 19:39:14 +00:00
|
|
|
GrowableArray<BlockEntryInstr*>* postorder,
|
2012-05-16 13:28:02 +00:00
|
|
|
GrowableArray<intptr_t>* parent,
|
|
|
|
GrowableArray<BitVector*>* assigned_vars,
|
2012-07-26 13:21:39 +00:00
|
|
|
intptr_t variable_count,
|
|
|
|
intptr_t fixed_parameter_count) {
|
2012-05-16 12:10:02 +00:00
|
|
|
// We have already visited the graph entry, so we can assume current_block
|
|
|
|
// is non-null and preorder array is non-empty.
|
2012-03-19 19:39:14 +00:00
|
|
|
ASSERT(current_block != NULL);
|
|
|
|
ASSERT(!preorder->is_empty());
|
|
|
|
|
|
|
|
// 1. Record control-flow-graph basic-block predecessors.
|
2012-05-16 13:28:02 +00:00
|
|
|
AddPredecessor(current_block);
|
2012-03-19 19:39:14 +00:00
|
|
|
|
2012-05-16 13:28:02 +00:00
|
|
|
// 2. If the block has already been reached by the traversal, we are
|
|
|
|
// done. Blocks with a single predecessor cannot have been reached
|
|
|
|
// before.
|
|
|
|
ASSERT(!IsTargetEntry() || (preorder_number() == -1));
|
2012-03-16 22:20:04 +00:00
|
|
|
if (preorder_number() >= 0) return;
|
2012-03-19 19:39:14 +00:00
|
|
|
|
2012-07-04 10:24:19 +00:00
|
|
|
// 3. The current block is the spanning-tree parent.
|
|
|
|
parent->Add(current_block->preorder_number());
|
2012-03-19 19:39:14 +00:00
|
|
|
|
|
|
|
// 4. Assign preorder number and add the block entry to the list.
|
2012-05-16 13:28:02 +00:00
|
|
|
// Allocate an empty set of assigned variables for the block.
|
2012-07-04 10:24:19 +00:00
|
|
|
set_preorder_number(preorder->length());
|
2012-03-16 22:20:04 +00:00
|
|
|
preorder->Add(this);
|
2012-05-16 13:28:02 +00:00
|
|
|
BitVector* vars =
|
|
|
|
(variable_count == 0) ? NULL : new BitVector(variable_count);
|
|
|
|
assigned_vars->Add(vars);
|
|
|
|
// The preorder, parent, and assigned_vars arrays are all indexed by
|
|
|
|
// preorder block number, so they should stay in lockstep.
|
2012-03-19 19:39:14 +00:00
|
|
|
ASSERT(preorder->length() == parent->length());
|
2012-05-16 13:28:02 +00:00
|
|
|
ASSERT(preorder->length() == assigned_vars->length());
|
2012-03-19 19:39:14 +00:00
|
|
|
|
2012-03-19 21:57:06 +00:00
|
|
|
// 5. Iterate straight-line successors until a branch instruction or
|
|
|
|
// another basic block entry instruction, and visit that instruction.
|
2012-07-09 11:38:29 +00:00
|
|
|
ASSERT(next() != NULL);
|
2012-08-06 10:43:47 +00:00
|
|
|
ASSERT(!next()->IsBlockEntry());
|
2012-07-09 11:38:29 +00:00
|
|
|
Instruction* next_instr = next();
|
2012-08-06 10:43:47 +00:00
|
|
|
while ((next_instr != NULL) &&
|
|
|
|
!next_instr->IsBlockEntry() &&
|
2012-08-27 09:30:20 +00:00
|
|
|
!next_instr->IsControl()) {
|
2012-08-06 10:43:47 +00:00
|
|
|
if (vars != NULL) {
|
|
|
|
next_instr->RecordAssignedVars(vars, fixed_parameter_count);
|
2012-05-16 13:28:02 +00:00
|
|
|
}
|
2012-08-06 10:43:47 +00:00
|
|
|
set_last_instruction(next_instr);
|
|
|
|
GotoInstr* goto_instr = next_instr->AsGoto();
|
|
|
|
next_instr =
|
|
|
|
(goto_instr != NULL) ? goto_instr->successor() : next_instr->next();
|
2012-03-19 21:57:06 +00:00
|
|
|
}
|
2012-07-09 11:38:29 +00:00
|
|
|
if (next_instr != NULL) {
|
|
|
|
next_instr->DiscoverBlocks(this, preorder, postorder,
|
2012-07-26 13:21:39 +00:00
|
|
|
parent, assigned_vars,
|
|
|
|
variable_count, fixed_parameter_count);
|
2012-03-19 21:57:06 +00:00
|
|
|
}
|
2012-03-19 19:39:14 +00:00
|
|
|
|
|
|
|
// 6. Assign postorder number and add the block entry to the list.
|
2012-03-16 22:20:04 +00:00
|
|
|
set_postorder_number(postorder->length());
|
|
|
|
postorder->Add(this);
|
2012-03-07 10:24:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-06 13:21:20 +00:00
|
|
|
bool BlockEntryInstr::Dominates(BlockEntryInstr* other) const {
|
|
|
|
// TODO(fschneider): Make this faster by e.g. storing dominators for each
|
|
|
|
// block while computing the dominator tree.
|
|
|
|
ASSERT(other != NULL);
|
|
|
|
BlockEntryInstr* current = other;
|
|
|
|
while (current != NULL && current != this) {
|
|
|
|
current = current->dominator();
|
|
|
|
}
|
|
|
|
return current == this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-27 09:30:20 +00:00
|
|
|
void ControlInstruction::DiscoverBlocks(
|
2012-03-19 19:39:14 +00:00
|
|
|
BlockEntryInstr* current_block,
|
2012-03-16 22:20:04 +00:00
|
|
|
GrowableArray<BlockEntryInstr*>* preorder,
|
2012-03-19 19:39:14 +00:00
|
|
|
GrowableArray<BlockEntryInstr*>* postorder,
|
2012-05-16 13:28:02 +00:00
|
|
|
GrowableArray<intptr_t>* parent,
|
|
|
|
GrowableArray<BitVector*>* assigned_vars,
|
2012-07-26 13:21:39 +00:00
|
|
|
intptr_t variable_count,
|
|
|
|
intptr_t fixed_parameter_count) {
|
2012-03-19 19:39:14 +00:00
|
|
|
current_block->set_last_instruction(this);
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
// Visit the false successor before the true successor so they appear in
|
2012-03-16 22:20:04 +00:00
|
|
|
// true/false order in reverse postorder used as the block ordering in the
|
|
|
|
// nonoptimizing compiler.
|
2012-03-09 21:34:58 +00:00
|
|
|
ASSERT(true_successor_ != NULL);
|
2012-03-16 22:20:04 +00:00
|
|
|
ASSERT(false_successor_ != NULL);
|
2012-05-18 01:04:56 +00:00
|
|
|
false_successor_->DiscoverBlocks(current_block, preorder, postorder,
|
2012-07-26 13:21:39 +00:00
|
|
|
parent, assigned_vars,
|
|
|
|
variable_count, fixed_parameter_count);
|
2012-05-18 01:04:56 +00:00
|
|
|
true_successor_->DiscoverBlocks(current_block, preorder, postorder,
|
2012-07-26 13:21:39 +00:00
|
|
|
parent, assigned_vars,
|
|
|
|
variable_count, fixed_parameter_count);
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-13 13:36:04 +00:00
|
|
|
void JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) {
|
|
|
|
// Lazily initialize the array of phis.
|
|
|
|
// Currently, phis are stored in a sparse array that holds the phi
|
|
|
|
// for variable with index i at position i.
|
|
|
|
// TODO(fschneider): Store phis in a more compact way.
|
|
|
|
if (phis_ == NULL) {
|
|
|
|
phis_ = new ZoneGrowableArray<PhiInstr*>(var_count);
|
|
|
|
for (intptr_t i = 0; i < var_count; i++) {
|
|
|
|
phis_->Add(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ASSERT((*phis_)[var_index] == NULL);
|
2012-08-30 20:39:48 +00:00
|
|
|
(*phis_)[var_index] = new PhiInstr(this, PredecessorCount());
|
2012-06-13 13:36:04 +00:00
|
|
|
phi_count_++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-08 12:38:21 +00:00
|
|
|
void JoinEntryInstr::RemoveDeadPhis() {
|
|
|
|
if (phis_ == NULL) return;
|
|
|
|
|
|
|
|
for (intptr_t i = 0; i < phis_->length(); i++) {
|
|
|
|
PhiInstr* phi = (*phis_)[i];
|
|
|
|
if ((phi != NULL) && !phi->is_alive()) {
|
|
|
|
(*phis_)[i] = NULL;
|
|
|
|
phi_count_--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we removed all phis.
|
|
|
|
if (phi_count_ == 0) phis_ = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-06 11:09:02 +00:00
|
|
|
intptr_t Instruction::SuccessorCount() const {
|
2012-07-18 13:44:12 +00:00
|
|
|
return 0;
|
2012-06-06 11:09:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BlockEntryInstr* Instruction::SuccessorAt(intptr_t index) const {
|
2012-07-18 13:44:12 +00:00
|
|
|
// Called only if index is in range. Only control-transfer instructions
|
|
|
|
// can have non-zero successor counts and they override this function.
|
|
|
|
UNREACHABLE();
|
|
|
|
return NULL;
|
2012-07-02 16:08:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-06 11:09:02 +00:00
|
|
|
intptr_t GraphEntryInstr::SuccessorCount() const {
|
|
|
|
return 1 + catch_entries_.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BlockEntryInstr* GraphEntryInstr::SuccessorAt(intptr_t index) const {
|
|
|
|
if (index == 0) return normal_entry_;
|
|
|
|
return catch_entries_[index - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-27 09:30:20 +00:00
|
|
|
intptr_t ControlInstruction::SuccessorCount() const {
|
2012-06-06 11:09:02 +00:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-27 09:30:20 +00:00
|
|
|
BlockEntryInstr* ControlInstruction::SuccessorAt(intptr_t index) const {
|
2012-06-06 11:09:02 +00:00
|
|
|
if (index == 0) return true_successor_;
|
|
|
|
if (index == 1) return false_successor_;
|
|
|
|
UNREACHABLE();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-18 13:44:12 +00:00
|
|
|
intptr_t GotoInstr::SuccessorCount() const {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BlockEntryInstr* GotoInstr::SuccessorAt(intptr_t index) const {
|
|
|
|
ASSERT(index == 0);
|
|
|
|
return successor();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Instruction::Goto(JoinEntryInstr* entry) {
|
|
|
|
set_next(new GotoInstr(entry));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-30 09:08:27 +00:00
|
|
|
RawAbstractType* Value::CompileType() const {
|
2012-08-13 16:56:10 +00:00
|
|
|
if (definition()->HasPropagatedType()) {
|
|
|
|
return definition()->PropagatedType();
|
|
|
|
}
|
|
|
|
// The compile type may be requested when building the flow graph, i.e. before
|
|
|
|
// type propagation has occurred. To avoid repeatedly computing the compile
|
|
|
|
// type of the definition, we store it as initial propagated type.
|
|
|
|
AbstractType& type = AbstractType::Handle(definition()->CompileType());
|
|
|
|
definition()->SetPropagatedType(type);
|
|
|
|
return type.raw();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-30 09:08:27 +00:00
|
|
|
intptr_t Value::ResultCid() const {
|
2012-08-16 17:39:37 +00:00
|
|
|
return definition()->GetPropagatedCid();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-21 13:36:36 +00:00
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* ConstantInstr::CompileType() const {
|
2012-08-29 12:56:57 +00:00
|
|
|
if (value().IsNull()) {
|
|
|
|
return Type::NullType();
|
|
|
|
}
|
|
|
|
if (value().IsInstance()) {
|
|
|
|
return Instance::Cast(value()).GetType();
|
|
|
|
} else {
|
|
|
|
ASSERT(value().IsAbstractTypeArguments());
|
|
|
|
return AbstractType::null();
|
|
|
|
}
|
2012-08-21 13:36:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t ConstantInstr::ResultCid() const {
|
2012-08-29 12:56:57 +00:00
|
|
|
if (value().IsNull()) {
|
|
|
|
return kNullCid;
|
|
|
|
}
|
|
|
|
if (value().IsInstance()) {
|
|
|
|
return Class::Handle(value().clazz()).id();
|
|
|
|
} else {
|
|
|
|
ASSERT(value().IsAbstractTypeArguments());
|
|
|
|
return kDynamicCid;
|
|
|
|
}
|
2012-08-21 13:36:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* AssertAssignableInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
const AbstractType& value_compile_type =
|
|
|
|
AbstractType::Handle(value()->CompileType());
|
|
|
|
if (!value_compile_type.IsNull() &&
|
|
|
|
value_compile_type.IsMoreSpecificThan(dst_type(), NULL)) {
|
|
|
|
return value_compile_type.raw();
|
2012-07-26 16:04:36 +00:00
|
|
|
}
|
2012-05-16 23:21:24 +00:00
|
|
|
return dst_type().raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* AssertBooleanInstr::CompileType() const {
|
2012-08-27 21:09:23 +00:00
|
|
|
return Type::BoolType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* ArgumentDefinitionTestInstr::CompileType() const {
|
2012-08-30 22:46:44 +00:00
|
|
|
return Type::BoolType();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CurrentContextInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StoreContextInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* ClosureCallInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
// Because of function subtyping rules, the declared return type of a closure
|
|
|
|
// call cannot be relied upon for compile type analysis. For example, a
|
2012-07-09 18:02:40 +00:00
|
|
|
// function returning Dynamic can be assigned to a closure variable declared
|
|
|
|
// to return int and may actually return a double at run-time.
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* InstanceCallInstr::CompileType() const {
|
2012-07-26 16:04:36 +00:00
|
|
|
// TODO(regis): Return a more specific type than Dynamic for recognized
|
2012-08-10 01:26:13 +00:00
|
|
|
// combinations of receiver type and method name.
|
2012-05-16 23:21:24 +00:00
|
|
|
return Type::DynamicType();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* PolymorphicInstanceCallInstr::CompileType() const {
|
2012-06-13 18:48:46 +00:00
|
|
|
return Type::DynamicType();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StaticCallInstr::CompileType() const {
|
2012-08-15 23:49:12 +00:00
|
|
|
if (FLAG_enable_type_checks) {
|
|
|
|
return function().result_type();
|
|
|
|
}
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* LoadLocalInstr::CompileType() const {
|
2012-07-26 16:04:36 +00:00
|
|
|
if (FLAG_enable_type_checks) {
|
|
|
|
return local().type().raw();
|
|
|
|
}
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StoreLocalInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
return value()->CompileType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StrictCompareInstr::CompileType() const {
|
2012-08-27 21:09:23 +00:00
|
|
|
return Type::BoolType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-13 23:44:07 +00:00
|
|
|
// Only known == targets return a Boolean.
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* EqualityCompareInstr::CompileType() const {
|
2012-08-13 23:44:07 +00:00
|
|
|
if ((receiver_class_id() == kSmiCid) ||
|
|
|
|
(receiver_class_id() == kDoubleCid) ||
|
|
|
|
(receiver_class_id() == kNumberCid)) {
|
2012-08-27 21:09:23 +00:00
|
|
|
return Type::BoolType();
|
2012-08-13 23:44:07 +00:00
|
|
|
}
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t EqualityCompareInstr::ResultCid() const {
|
2012-08-16 22:22:57 +00:00
|
|
|
if ((receiver_class_id() == kSmiCid) ||
|
|
|
|
(receiver_class_id() == kDoubleCid) ||
|
|
|
|
(receiver_class_id() == kNumberCid)) {
|
|
|
|
// Known/library equalities that are guaranteed to return Boolean.
|
|
|
|
return kBoolCid;
|
|
|
|
}
|
|
|
|
return kDynamicCid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* RelationalOpInstr::CompileType() const {
|
2012-08-13 23:44:07 +00:00
|
|
|
if ((operands_class_id() == kSmiCid) ||
|
|
|
|
(operands_class_id() == kDoubleCid) ||
|
|
|
|
(operands_class_id() == kNumberCid)) {
|
2012-08-16 22:22:57 +00:00
|
|
|
// Known/library relational ops that are guaranteed to return Boolean.
|
2012-08-27 21:09:23 +00:00
|
|
|
return Type::BoolType();
|
2012-08-13 23:44:07 +00:00
|
|
|
}
|
|
|
|
return Type::DynamicType();
|
2012-06-11 17:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t RelationalOpInstr::ResultCid() const {
|
2012-08-16 22:22:57 +00:00
|
|
|
if ((operands_class_id() == kSmiCid) ||
|
|
|
|
(operands_class_id() == kDoubleCid) ||
|
|
|
|
(operands_class_id() == kNumberCid)) {
|
|
|
|
// Known/library relational ops that are guaranteed to return Boolean.
|
|
|
|
return kBoolCid;
|
|
|
|
}
|
|
|
|
return kDynamicCid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* NativeCallInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
// The result type of the native function is identical to the result type of
|
2012-05-17 18:47:45 +00:00
|
|
|
// the enclosing native Dart function. However, we prefer to check the type
|
|
|
|
// of the value returned from the native call.
|
2012-05-16 23:21:24 +00:00
|
|
|
return Type::DynamicType();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* LoadIndexedInstr::CompileType() const {
|
2012-06-08 19:36:26 +00:00
|
|
|
return Type::DynamicType();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StoreIndexedInstr::CompileType() const {
|
2012-05-30 15:55:46 +00:00
|
|
|
return AbstractType::null();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* LoadInstanceFieldInstr::CompileType() const {
|
2012-07-26 16:04:36 +00:00
|
|
|
if (FLAG_enable_type_checks) {
|
|
|
|
return field().type();
|
|
|
|
}
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StoreInstanceFieldInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
return value()->CompileType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* LoadStaticFieldInstr::CompileType() const {
|
2012-07-26 16:04:36 +00:00
|
|
|
if (FLAG_enable_type_checks) {
|
|
|
|
return field().type();
|
|
|
|
}
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StoreStaticFieldInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
return value()->CompileType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* BooleanNegateInstr::CompileType() const {
|
2012-08-27 21:09:23 +00:00
|
|
|
return Type::BoolType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* InstanceOfInstr::CompileType() const {
|
2012-08-27 21:09:23 +00:00
|
|
|
return Type::BoolType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CreateArrayInstr::CompileType() const {
|
2012-08-24 18:17:11 +00:00
|
|
|
return type().raw();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CreateClosureInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
const Function& fun = function();
|
|
|
|
const Class& signature_class = Class::Handle(fun.signature_class());
|
2012-07-20 16:08:43 +00:00
|
|
|
return signature_class.SignatureType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* AllocateObjectInstr::CompileType() const {
|
2012-08-01 17:15:55 +00:00
|
|
|
// TODO(regis): Be more specific.
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* AllocateObjectWithBoundsCheckInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
// TODO(regis): Be more specific.
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* LoadVMFieldInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
// Type may be null if the field is a VM field, e.g. context parent.
|
2012-08-23 21:04:13 +00:00
|
|
|
// Keep it as null for debug purposes and do not return Dynamic in production
|
|
|
|
// mode, since misuse of the type would remain undetected.
|
|
|
|
if (type().IsNull()) {
|
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
if (FLAG_enable_type_checks) {
|
|
|
|
return type().raw();
|
|
|
|
}
|
|
|
|
return Type::DynamicType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* StoreVMFieldInstr::CompileType() const {
|
2012-08-10 01:26:13 +00:00
|
|
|
return value()->CompileType();
|
2012-05-16 23:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* InstantiateTypeArgumentsInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* ExtractConstructorTypeArgumentsInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* ExtractConstructorInstantiatorInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* AllocateContextInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* ChainContextInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CloneContextInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CatchEntryInstr::CompileType() const {
|
2012-05-16 23:21:24 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CheckStackOverflowInstr::CompileType() const {
|
2012-08-11 00:09:12 +00:00
|
|
|
return AbstractType::null();
|
2012-06-11 17:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* BinarySmiOpInstr::CompileType() const {
|
2012-08-23 21:04:13 +00:00
|
|
|
return (op_kind() == Token::kSHL) ? Type::IntInterface() : Type::SmiType();
|
2012-08-16 22:22:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t BinarySmiOpInstr::ResultCid() const {
|
2012-08-16 22:22:57 +00:00
|
|
|
return (op_kind() == Token::kSHL) ? kDynamicCid : kSmiCid;
|
2012-05-24 16:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
bool BinarySmiOpInstr::CanDeoptimize() const {
|
2012-08-23 08:24:29 +00:00
|
|
|
switch (op_kind()) {
|
|
|
|
case Token::kBIT_AND:
|
|
|
|
case Token::kBIT_OR:
|
|
|
|
case Token::kBIT_XOR:
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* BinaryMintOpInstr::CompileType() const {
|
2012-08-23 21:04:13 +00:00
|
|
|
return Type::MintType();
|
2012-08-22 11:17:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t BinaryMintOpInstr::ResultCid() const {
|
2012-08-22 11:17:57 +00:00
|
|
|
return kMintCid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* UnboxedDoubleBinaryOpInstr::CompileType() const {
|
2012-08-30 17:29:49 +00:00
|
|
|
return Type::Double();
|
2012-08-24 14:45:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-11 14:52:32 +00:00
|
|
|
RawAbstractType* MathSqrtInstr::CompileType() const {
|
|
|
|
return Type::Double();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* UnboxDoubleInstr::CompileType() const {
|
2012-08-24 14:45:42 +00:00
|
|
|
return Type::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
intptr_t BoxDoubleInstr::ResultCid() const {
|
2012-08-24 14:45:42 +00:00
|
|
|
return kDoubleCid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* BoxDoubleInstr::CompileType() const {
|
2012-08-30 17:29:49 +00:00
|
|
|
return Type::Double();
|
2012-08-24 14:45:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* UnarySmiOpInstr::CompileType() const {
|
2012-08-23 21:04:13 +00:00
|
|
|
return Type::SmiType();
|
2012-05-31 20:38:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* NumberNegateInstr::CompileType() const {
|
2012-08-16 22:22:57 +00:00
|
|
|
// Implemented only for doubles.
|
2012-08-30 17:29:49 +00:00
|
|
|
return Type::Double();
|
2012-05-31 20:38:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* DoubleToDoubleInstr::CompileType() const {
|
2012-08-30 17:29:49 +00:00
|
|
|
return Type::Double();
|
2012-08-15 11:31:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* SmiToDoubleInstr::CompileType() const {
|
2012-08-30 17:29:49 +00:00
|
|
|
return Type::Double();
|
2012-06-13 08:29:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CheckClassInstr::CompileType() const {
|
2012-08-20 12:40:14 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CheckSmiInstr::CompileType() const {
|
2012-08-23 08:24:29 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CheckArrayBoundInstr::CompileType() const {
|
2012-08-28 09:14:57 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
RawAbstractType* CheckEitherNonSmiInstr::CompileType() const {
|
2012-08-24 14:45:42 +00:00
|
|
|
return AbstractType::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-23 08:24:29 +00:00
|
|
|
// Optimizations that eliminate or simplify individual computations.
|
2012-09-05 17:04:49 +00:00
|
|
|
Definition* Definition::Canonicalize() {
|
|
|
|
return this;
|
2012-08-23 08:24:29 +00:00
|
|
|
}
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
Definition* StrictCompareInstr::Canonicalize() {
|
|
|
|
if (!right()->BindsToConstant()) return this;
|
2012-08-30 09:08:27 +00:00
|
|
|
const Object& right_constant = right()->BoundConstant();
|
|
|
|
Definition* left_defn = left()->definition();
|
2012-08-23 08:24:29 +00:00
|
|
|
// TODO(fschneider): Handle other cases: e === false and e !== true/false.
|
|
|
|
// Handles e === true.
|
|
|
|
if ((kind() == Token::kEQ_STRICT) &&
|
|
|
|
(right_constant.raw() == Bool::True()) &&
|
2012-08-30 09:08:27 +00:00
|
|
|
(left()->ResultCid() == kBoolCid)) {
|
2012-08-23 08:24:29 +00:00
|
|
|
// Remove the constant from the graph.
|
2012-09-05 17:04:49 +00:00
|
|
|
Definition* right_defn = right()->definition();
|
|
|
|
right_defn->RemoveFromGraph();
|
2012-08-23 08:24:29 +00:00
|
|
|
// Return left subexpression as the replacement for this instruction.
|
2012-08-30 09:08:27 +00:00
|
|
|
return left_defn;
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
2012-09-05 17:04:49 +00:00
|
|
|
return this;
|
2012-08-27 14:01:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
Definition* CheckClassInstr::Canonicalize() {
|
2012-08-27 14:01:27 +00:00
|
|
|
const intptr_t v_cid = value()->ResultCid();
|
2012-09-03 11:27:09 +00:00
|
|
|
const intptr_t num_checks = unary_checks().NumberOfChecks();
|
2012-08-27 14:01:27 +00:00
|
|
|
if ((num_checks == 1) &&
|
2012-09-03 11:27:09 +00:00
|
|
|
(v_cid == unary_checks().GetReceiverClassIdAt(0))) {
|
2012-08-27 14:01:27 +00:00
|
|
|
// No checks needed.
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-09-05 17:04:49 +00:00
|
|
|
return this;
|
2012-08-23 08:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
Definition* CheckSmiInstr::Canonicalize() {
|
|
|
|
return (value()->ResultCid() == kSmiCid) ? NULL : this;
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
Definition* CheckEitherNonSmiInstr::Canonicalize() {
|
2012-08-24 14:45:42 +00:00
|
|
|
if ((left()->ResultCid() == kDoubleCid) ||
|
|
|
|
(right()->ResultCid() == kDoubleCid)) {
|
|
|
|
return NULL; // Remove from the graph.
|
|
|
|
}
|
2012-09-05 17:04:49 +00:00
|
|
|
return this;
|
2012-08-24 14:45:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-23 08:24:29 +00:00
|
|
|
// Shared code generation methods (EmitNativeCode, MakeLocationSummary, and
|
|
|
|
// PrepareEntry). Only assembly code that can be shared across all architectures
|
|
|
|
// can be used. Machine specific register allocation and code generation
|
|
|
|
// is located in intermediate_language_<arch>.cc
|
|
|
|
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
#define __ compiler->assembler()->
|
|
|
|
|
|
|
|
void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
|
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
|
|
|
|
__ Bind(compiler->GetBlockLabel(this));
|
2012-07-31 16:28:09 +00:00
|
|
|
if (HasParallelMove()) {
|
|
|
|
compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
|
|
|
|
}
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
|
|
|
|
__ Bind(compiler->GetBlockLabel(this));
|
2012-08-29 16:44:18 +00:00
|
|
|
if (IsCatchEntry()) {
|
|
|
|
compiler->AddExceptionHandler(catch_try_index(),
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
compiler->assembler()->CodeSize());
|
|
|
|
}
|
2012-07-31 16:28:09 +00:00
|
|
|
if (HasParallelMove()) {
|
|
|
|
compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
|
|
|
|
}
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* GraphEntryInstr::MakeLocationSummary() const {
|
|
|
|
UNREACHABLE();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LocationSummary* JoinEntryInstr::MakeLocationSummary() const {
|
|
|
|
UNREACHABLE();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LocationSummary* TargetEntryInstr::MakeLocationSummary() const {
|
|
|
|
UNREACHABLE();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LocationSummary* PhiInstr::MakeLocationSummary() const {
|
|
|
|
UNREACHABLE();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PhiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LocationSummary* ParameterInstr::MakeLocationSummary() const {
|
|
|
|
UNREACHABLE();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LocationSummary* ParallelMoveInstr::MakeLocationSummary() const {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
LocationSummary* ThrowInstr::MakeLocationSummary() const {
|
2012-08-02 15:54:42 +00:00
|
|
|
return new LocationSummary(0, 0, LocationSummary::kCall);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
2012-08-31 15:46:10 +00:00
|
|
|
compiler->GenerateCallRuntime(token_pos(),
|
2012-08-14 06:59:24 +00:00
|
|
|
kThrowRuntimeEntry,
|
2012-08-23 10:08:37 +00:00
|
|
|
locs());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ int3();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LocationSummary* ReThrowInstr::MakeLocationSummary() const {
|
2012-08-02 15:54:42 +00:00
|
|
|
return new LocationSummary(0, 0, LocationSummary::kCall);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
2012-08-31 15:46:10 +00:00
|
|
|
compiler->GenerateCallRuntime(token_pos(),
|
2012-08-14 06:59:24 +00:00
|
|
|
kReThrowRuntimeEntry,
|
2012-08-23 10:08:37 +00:00
|
|
|
locs());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ int3();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-18 13:44:12 +00:00
|
|
|
LocationSummary* GotoInstr::MakeLocationSummary() const {
|
2012-07-31 11:51:47 +00:00
|
|
|
return new LocationSummary(0, 0, LocationSummary::kNoCall);
|
2012-07-18 13:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
2012-09-06 13:21:20 +00:00
|
|
|
// Add deoptimization descriptor for deoptimizing instructions
|
|
|
|
// that may be inserted before this instruction.
|
|
|
|
compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
|
|
|
|
GetDeoptId(),
|
|
|
|
0); // No token position.
|
|
|
|
|
2012-07-31 16:28:09 +00:00
|
|
|
if (HasParallelMove()) {
|
|
|
|
compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
|
|
|
|
}
|
|
|
|
|
2012-07-18 13:44:12 +00:00
|
|
|
// We can fall through if the successor is the next block in the list.
|
|
|
|
// Otherwise, we need a jump.
|
|
|
|
if (!compiler->IsNextBlock(successor())) {
|
|
|
|
__ jmp(compiler->GetBlockLabel(successor()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-13 16:23:14 +00:00
|
|
|
static Condition NegateCondition(Condition condition) {
|
|
|
|
switch (condition) {
|
|
|
|
case EQUAL: return NOT_EQUAL;
|
|
|
|
case NOT_EQUAL: return EQUAL;
|
|
|
|
case LESS: return GREATER_EQUAL;
|
|
|
|
case LESS_EQUAL: return GREATER;
|
|
|
|
case GREATER: return LESS_EQUAL;
|
|
|
|
case GREATER_EQUAL: return LESS;
|
|
|
|
case BELOW: return ABOVE_EQUAL;
|
|
|
|
case BELOW_EQUAL: return ABOVE;
|
|
|
|
case ABOVE: return BELOW_EQUAL;
|
|
|
|
case ABOVE_EQUAL: return BELOW;
|
|
|
|
default:
|
|
|
|
OS::Print("Error %d\n", condition);
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return EQUAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-06 13:27:30 +00:00
|
|
|
void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
|
|
|
|
bool value) {
|
|
|
|
if (value && compiler->IsNextBlock(false_successor())) {
|
|
|
|
__ jmp(compiler->GetBlockLabel(true_successor()));
|
|
|
|
} else if (!value && compiler->IsNextBlock(true_successor())) {
|
|
|
|
__ jmp(compiler->GetBlockLabel(false_successor()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-27 09:30:20 +00:00
|
|
|
void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
|
|
|
|
Condition true_condition) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
if (compiler->IsNextBlock(false_successor())) {
|
2012-06-13 16:23:14 +00:00
|
|
|
// If the next block is the false successor we will fall through to it.
|
|
|
|
__ j(true_condition, compiler->GetBlockLabel(true_successor()));
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
} else {
|
|
|
|
// If the next block is the true successor we negate comparison and fall
|
|
|
|
// through to it.
|
2012-06-13 16:23:14 +00:00
|
|
|
ASSERT(compiler->IsNextBlock(true_successor()));
|
|
|
|
Condition false_condition = NegateCondition(true_condition);
|
|
|
|
__ j(false_condition, compiler->GetBlockLabel(false_successor()));
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
|
2012-07-31 11:51:47 +00:00
|
|
|
return LocationSummary::Make(0,
|
|
|
|
Location::RequiresRegister(),
|
|
|
|
LocationSummary::kNoCall);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ MoveRegister(locs()->out().reg(), CTX);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* StoreContextInstr::MakeLocationSummary() const {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
const intptr_t kNumInputs = 1;
|
|
|
|
const intptr_t kNumTemps = 0;
|
2012-07-31 11:51:47 +00:00
|
|
|
LocationSummary* summary =
|
|
|
|
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
summary->set_in(0, Location::RegisterLocation(CTX));
|
|
|
|
return summary;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void StoreContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
// Nothing to do. Context register were loaded by register allocator.
|
|
|
|
ASSERT(locs()->in(0).reg() == CTX);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
|
2012-07-31 11:51:47 +00:00
|
|
|
return LocationSummary::Make(2,
|
|
|
|
Location::SameAsFirstInput(),
|
|
|
|
LocationSummary::kNoCall);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
Register left = locs()->in(0).reg();
|
|
|
|
Register right = locs()->in(1).reg();
|
|
|
|
|
2012-06-13 16:23:14 +00:00
|
|
|
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
|
|
|
Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ CompareRegisters(left, right);
|
2012-06-13 16:23:14 +00:00
|
|
|
|
2012-07-19 15:52:44 +00:00
|
|
|
Register result = locs()->out().reg();
|
|
|
|
Label load_true, done;
|
|
|
|
__ j(true_condition, &load_true, Assembler::kNearJump);
|
|
|
|
__ LoadObject(result, compiler->bool_false());
|
|
|
|
__ jmp(&done, Assembler::kNearJump);
|
|
|
|
__ Bind(&load_true);
|
|
|
|
__ LoadObject(result, compiler->bool_true());
|
|
|
|
__ Bind(&done);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
2012-08-29 09:07:11 +00:00
|
|
|
BranchInstr* branch) {
|
|
|
|
Register left = locs()->in(0).reg();
|
|
|
|
Register right = locs()->in(1).reg();
|
|
|
|
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
|
|
|
Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
|
|
|
|
__ CompareRegisters(left, right);
|
|
|
|
branch->EmitBranchOnCondition(compiler, true_condition);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
// The arguments to the stub include the closure. The arguments
|
|
|
|
// descriptor describes the closure's arguments (and so does not include
|
|
|
|
// the closure).
|
|
|
|
Register temp_reg = locs()->temp(0).reg();
|
|
|
|
int argument_count = ArgumentCount();
|
|
|
|
const Array& arguments_descriptor =
|
2012-06-26 17:43:44 +00:00
|
|
|
DartEntry::ArgumentsDescriptor(argument_count - 1,
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
argument_names());
|
|
|
|
__ LoadObject(temp_reg, arguments_descriptor);
|
2012-08-30 18:53:46 +00:00
|
|
|
compiler->GenerateDartCall(deopt_id(),
|
|
|
|
token_pos(),
|
|
|
|
&StubCode::CallClosureFunctionLabel(),
|
|
|
|
PcDescriptors::kOther,
|
|
|
|
locs());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ Drop(argument_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* InstanceCallInstr::MakeLocationSummary() const {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
return MakeCallSummary();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
2012-08-30 18:53:46 +00:00
|
|
|
compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
|
2012-08-06 20:24:03 +00:00
|
|
|
deopt_id(),
|
2012-08-29 16:44:18 +00:00
|
|
|
token_pos());
|
2012-08-06 20:24:03 +00:00
|
|
|
compiler->GenerateInstanceCall(deopt_id(),
|
2012-06-22 20:37:01 +00:00
|
|
|
token_pos(),
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
function_name(),
|
|
|
|
ArgumentCount(),
|
|
|
|
argument_names(),
|
2012-08-14 06:59:24 +00:00
|
|
|
checked_argument_count(),
|
2012-08-23 10:08:37 +00:00
|
|
|
locs());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* StaticCallInstr::MakeLocationSummary() const {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
return MakeCallSummary();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
2012-08-06 20:24:03 +00:00
|
|
|
compiler->GenerateStaticCall(deopt_id(),
|
2012-06-22 20:37:01 +00:00
|
|
|
token_pos(),
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
function(),
|
|
|
|
ArgumentCount(),
|
2012-08-14 06:59:24 +00:00
|
|
|
argument_names(),
|
2012-08-23 10:08:37 +00:00
|
|
|
locs());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
2012-08-13 22:37:22 +00:00
|
|
|
if (!is_eliminated()) {
|
2012-08-31 15:46:10 +00:00
|
|
|
compiler->GenerateAssertAssignable(token_pos(),
|
2012-08-10 01:26:13 +00:00
|
|
|
dst_type(),
|
2012-08-14 06:59:24 +00:00
|
|
|
dst_name(),
|
2012-08-23 10:08:37 +00:00
|
|
|
locs());
|
2012-08-10 01:26:13 +00:00
|
|
|
}
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
ASSERT(locs()->in(0).reg() == locs()->out().reg());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
|
2012-07-31 11:51:47 +00:00
|
|
|
return LocationSummary::Make(1,
|
|
|
|
Location::RequiresRegister(),
|
|
|
|
LocationSummary::kNoCall);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
Register value = locs()->in(0).reg();
|
|
|
|
Register result = locs()->out().reg();
|
|
|
|
|
|
|
|
Label done;
|
2012-06-13 16:23:14 +00:00
|
|
|
__ LoadObject(result, compiler->bool_true());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ CompareRegisters(result, value);
|
|
|
|
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
|
2012-06-13 16:23:14 +00:00
|
|
|
__ LoadObject(result, compiler->bool_false());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ Bind(&done);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* ChainContextInstr::MakeLocationSummary() const {
|
2012-07-31 11:51:47 +00:00
|
|
|
return LocationSummary::Make(1,
|
|
|
|
Location::NoLocation(),
|
|
|
|
LocationSummary::kNoCall);
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
Register context_value = locs()->in(0).reg();
|
|
|
|
|
|
|
|
// Chain the new context in context_value to its parent in CTX.
|
|
|
|
__ StoreIntoObject(context_value,
|
|
|
|
FieldAddress(context_value, Context::parent_offset()),
|
|
|
|
CTX);
|
|
|
|
// Set new context as current context.
|
|
|
|
__ MoveRegister(CTX, context_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
|
2012-09-11 12:50:52 +00:00
|
|
|
const intptr_t kNumInputs = 2;
|
|
|
|
const intptr_t kNumTemps = 0;
|
|
|
|
LocationSummary* locs =
|
|
|
|
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
|
|
|
locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
|
|
|
|
: Location::RequiresRegister());
|
|
|
|
locs->set_in(1, Location::RequiresRegister());
|
|
|
|
return locs;
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
Register value_reg = locs()->in(0).reg();
|
|
|
|
Register dest_reg = locs()->in(1).reg();
|
|
|
|
|
2012-08-25 00:27:07 +00:00
|
|
|
if (value()->NeedsStoreBuffer()) {
|
|
|
|
__ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()),
|
|
|
|
value_reg);
|
|
|
|
} else {
|
|
|
|
__ StoreIntoObjectNoBarrier(
|
|
|
|
dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg);
|
|
|
|
}
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
return MakeCallSummary();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
2012-08-14 00:38:01 +00:00
|
|
|
const Class& cls = Class::ZoneHandle(constructor().Owner());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
|
|
|
|
const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
|
2012-06-22 20:37:01 +00:00
|
|
|
compiler->GenerateCall(token_pos(),
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
&label,
|
2012-08-14 06:59:24 +00:00
|
|
|
PcDescriptors::kOther,
|
2012-08-23 10:08:37 +00:00
|
|
|
locs());
|
2012-08-09 19:34:41 +00:00
|
|
|
__ Drop(ArgumentCount()); // Discard arguments.
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
return MakeCallSummary();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 17:04:49 +00:00
|
|
|
void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
const Function& closure_function = function();
|
|
|
|
const Code& stub = Code::Handle(
|
|
|
|
StubCode::GetAllocationStubForClosure(closure_function));
|
|
|
|
const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint());
|
2012-08-29 16:44:18 +00:00
|
|
|
compiler->GenerateCall(token_pos(),
|
|
|
|
&label,
|
2012-08-14 06:59:24 +00:00
|
|
|
PcDescriptors::kOther,
|
2012-08-23 10:08:37 +00:00
|
|
|
locs());
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
__ Drop(2); // Discard type arguments and receiver.
|
|
|
|
}
|
|
|
|
|
2012-06-14 18:07:43 +00:00
|
|
|
|
2012-07-26 14:10:29 +00:00
|
|
|
LocationSummary* PushArgumentInstr::MakeLocationSummary() const {
|
|
|
|
const intptr_t kNumInputs = 1;
|
|
|
|
const intptr_t kNumTemps= 0;
|
2012-07-31 11:51:47 +00:00
|
|
|
LocationSummary* locs =
|
|
|
|
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
2012-07-26 14:10:29 +00:00
|
|
|
// TODO(fschneider): Use Any() once it is supported by all code generators.
|
|
|
|
locs->set_in(0, Location::RequiresRegister());
|
|
|
|
return locs;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
|
// In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
|
2012-08-21 13:58:57 +00:00
|
|
|
// where PushArgument is handled by BindInstr::EmitNativeCode.
|
2012-07-26 14:10:29 +00:00
|
|
|
// TODO(fschneider): Avoid special-casing for SSA mode here.
|
2012-08-21 13:58:57 +00:00
|
|
|
if (compiler->is_optimizing()) {
|
2012-07-26 14:10:29 +00:00
|
|
|
ASSERT(locs()->in(0).IsRegister());
|
|
|
|
__ PushRegister(locs()->in(0).reg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-11 12:30:21 +00:00
|
|
|
Environment* Environment::From(const GrowableArray<Definition*>& definitions,
|
|
|
|
intptr_t fixed_parameter_count,
|
|
|
|
const Environment* outer) {
|
|
|
|
Environment* env =
|
|
|
|
new Environment(definitions.length(),
|
|
|
|
fixed_parameter_count,
|
|
|
|
Isolate::kNoDeoptId,
|
|
|
|
(outer == NULL) ? NULL : outer->DeepCopy());
|
2012-08-17 13:06:08 +00:00
|
|
|
for (intptr_t i = 0; i < definitions.length(); ++i) {
|
2012-09-11 12:30:21 +00:00
|
|
|
env->values_.Add(new Value(definitions[i]));
|
2012-08-17 13:06:08 +00:00
|
|
|
}
|
2012-09-11 12:30:21 +00:00
|
|
|
return env;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Environment* Environment::DeepCopy() const {
|
|
|
|
Environment* copy =
|
|
|
|
new Environment(values_.length(),
|
|
|
|
fixed_parameter_count_,
|
|
|
|
deopt_id_,
|
|
|
|
(outer_ == NULL) ? NULL : outer_->DeepCopy());
|
|
|
|
for (intptr_t i = 0; i < values_.length(); ++i) {
|
|
|
|
copy->values_.Add(values_[i]->Copy());
|
|
|
|
}
|
|
|
|
return copy;
|
2012-08-17 13:06:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-27 14:16:02 +00:00
|
|
|
// Copies the environment and updates the environment use lists.
|
2012-09-11 12:30:21 +00:00
|
|
|
void Environment::DeepCopyTo(Instruction* instr) const {
|
|
|
|
Environment* copy = DeepCopy();
|
|
|
|
intptr_t use_index = 0;
|
|
|
|
for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
|
|
|
|
Value* value = it.CurrentValue();
|
2012-08-30 09:08:27 +00:00
|
|
|
value->set_instruction(instr);
|
2012-09-11 12:30:21 +00:00
|
|
|
value->set_use_index(use_index++);
|
2012-08-30 09:08:27 +00:00
|
|
|
value->AddToEnvUseList();
|
2012-08-23 08:24:29 +00:00
|
|
|
}
|
2012-08-27 14:16:02 +00:00
|
|
|
instr->set_env(copy);
|
2012-08-23 08:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
More code for ia32, more shared code.
CreateArrayComp, EqualityCompareComp, StoreStaticField, LoadStaticField, StoreIndexedComp, StoreInstanceFieldComp, Throw, Rethrow, AssertBooleanComp.
Made more code shared, which has the disadvantage od splitting MakeLocationSummary from EmitNativeCode. Discuss.
Review URL: https://chromiumcodereview.appspot.com//10543013
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8343 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-06 15:42:07 +00:00
|
|
|
#undef __
|
2012-05-31 20:38:55 +00:00
|
|
|
|
Initial implementation of a flow-graph builder for Dart's AST.
Visit the AST and generate an instruction (ie, not basic-block) flow
graph.
The flow graph for the simple function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
is:
1: StoreLocal(f, #1)
2: StoreLocal(n, #5)
3: [join]
4: t0 <-LoadLocal(n)
5: t0 <-InstanceCall(>, t0, #0)
6: if t0 goto(7, 15)
7: [target]
8: t0 <-LoadLocal(f)
9: t1 <-LoadLocal(n)
10: t0 <-InstanceCall(*, t0, t1)
11: StoreLocal(f, t0)
12: t0 <-LoadLocal(n)
13: t0 <-InstanceCall(-, t0, #1)
14: StoreLocal(n, t0) goto 3
15: [target]
16: t0 <-LoadLocal(f)
17: StaticCall(print, t0)
18: return #null
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9414003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4460 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-22 15:20:13 +00:00
|
|
|
} // namespace dart
|