Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Unified Diff: runtime/vm/intermediate_language.h

Issue 539153002: Port and integrate the irregexp engine from V8 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Port remaining V8 regexp tests and fix exposed bugs. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/intermediate_language.h
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index e7933fcb63c2cf75952bee0dfd8a3d0db7d4bc2c..6d047e8e3052044ce7e36ee6ae87d05f34eca4b9 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -423,6 +423,7 @@ class EmbeddedArray<T, 0> {
M(GraphEntry) \
M(JoinEntry) \
M(TargetEntry) \
+ M(IndirectEntry) \
M(CatchBlockEntry) \
M(Phi) \
M(Redefinition) \
@@ -433,6 +434,7 @@ class EmbeddedArray<T, 0> {
M(Throw) \
M(ReThrow) \
M(Goto) \
+ M(IndirectGoto) \
M(Branch) \
M(AssertAssignable) \
M(AssertBoolean) \
@@ -452,6 +454,7 @@ class EmbeddedArray<T, 0> {
M(NativeCall) \
M(DebugStepCheck) \
M(LoadIndexed) \
+ M(LoadCodeUnits) \
M(StoreIndexed) \
M(StoreInstanceField) \
M(InitStaticField) \
@@ -491,6 +494,7 @@ class EmbeddedArray<T, 0> {
M(BinaryDoubleOp) \
M(MathUnary) \
M(MathMinMax) \
+ M(CaseInsensitiveCompareUC16) \
M(UnboxDouble) \
M(BoxDouble) \
M(BoxFloat32x4) \
@@ -886,6 +890,7 @@ FOR_EACH_ABSTRACT_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
friend class UnaryDoubleOpInstr;
friend class MathUnaryInstr;
friend class MathMinMaxInstr;
+ friend class CaseInsensitiveCompareUC16Instr;
Florian Schneider 2014/10/01 17:04:13 Not needed?
jgruber1 2014/10/03 18:59:51 Done, unneeded now that deopt_id_ is not accessed
friend class CheckClassInstr;
friend class CheckClassIdInstr;
friend class GuardFieldInstr;
@@ -901,10 +906,12 @@ FOR_EACH_ABSTRACT_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
friend class MergedMathInstr;
friend class FlowGraphOptimizer;
friend class LoadIndexedInstr;
+ friend class LoadCodeUnitsInstr;
friend class StoreIndexedInstr;
friend class StoreInstanceFieldInstr;
friend class ComparisonInstr;
friend class TargetEntryInstr;
+ friend class IndirectEntryInstr;
Florian Schneider 2014/10/01 17:04:13 Not needed?
jgruber1 2014/10/03 18:59:51 Done.
friend class JoinEntryInstr;
friend class InstanceOfInstr;
friend class PolymorphicInstanceCallInstr;
@@ -1187,6 +1194,9 @@ class BlockEntryInstr : public Instruction {
void set_block_id(intptr_t block_id) { block_id_ = block_id; }
+ intptr_t offset() const { return offset_; }
+ void set_offset(intptr_t offset) { offset_ = offset; }
+
// For all instruction in this block: Remove all inputs (including in the
// environment) from their definition's use lists for all instructions.
void ClearAllInstructions();
@@ -1202,6 +1212,7 @@ class BlockEntryInstr : public Instruction {
dominator_(NULL),
dominated_blocks_(1),
last_instruction_(NULL),
+ offset_(-1),
parallel_move_(NULL),
loop_info_(NULL) { }
@@ -1226,6 +1237,9 @@ class BlockEntryInstr : public Instruction {
GrowableArray<BlockEntryInstr*> dominated_blocks_;
Instruction* last_instruction_;
+ // Offset of this block from the start of the emitted code.
+ intptr_t offset_;
+
// Parallel move that will be used by linear scan register allocator to
// connect live ranges at the start of the block.
ParallelMoveInstr* parallel_move_;
@@ -1306,6 +1320,10 @@ class GraphEntryInstr : public BlockEntryInstr {
CatchBlockEntryInstr* GetCatchEntry(intptr_t index);
+ void AddIndirectEntry(IndirectEntryInstr* entry) {
+ indirect_entries_.Add(entry);
+ }
+
GrowableArray<Definition*>* initial_definitions() {
return &initial_definitions_;
}
@@ -1340,6 +1358,10 @@ class GraphEntryInstr : public BlockEntryInstr {
return catch_entries_;
}
+ const GrowableArray<IndirectEntryInstr*>& indirect_entries() const {
+ return indirect_entries_;
+ }
+
virtual void PrintTo(BufferFormatter* f) const;
private:
@@ -1349,6 +1371,8 @@ class GraphEntryInstr : public BlockEntryInstr {
const ParsedFunction* parsed_function_;
TargetEntryInstr* normal_entry_;
GrowableArray<CatchBlockEntryInstr*> catch_entries_;
+ // Indirect targets are blocks reachable only through indirect gotos.
+ GrowableArray<IndirectEntryInstr*> indirect_entries_;
GrowableArray<Definition*> initial_definitions_;
const intptr_t osr_id_;
intptr_t entry_count_;
@@ -1394,6 +1418,7 @@ class JoinEntryInstr : public BlockEntryInstr {
friend class BlockEntryInstr;
friend class InlineExitCollector;
friend class PolymorphicInliner;
+ friend class IndirectEntryInstr; // Access in il_printer.cc.
// Direct access to phis_ in order to resize it due to phi elimination.
friend class ConstantPropagator;
@@ -1473,6 +1498,25 @@ class TargetEntryInstr : public BlockEntryInstr {
};
+class IndirectEntryInstr : public JoinEntryInstr {
+ public:
+ IndirectEntryInstr(intptr_t block_id,
+ intptr_t indirect_id,
+ intptr_t try_index)
+ : JoinEntryInstr(block_id, try_index),
+ indirect_id_(indirect_id) { }
+
+ DECLARE_INSTRUCTION(IndirectEntry)
+
+ virtual void PrintTo(BufferFormatter* f) const;
+
+ intptr_t indirect_id() const { return indirect_id_; }
+
+ private:
+ const intptr_t indirect_id_;
+};
+
+
class CatchBlockEntryInstr : public BlockEntryInstr {
public:
CatchBlockEntryInstr(intptr_t block_id,
@@ -2141,6 +2185,73 @@ class GotoInstr : public TemplateInstruction<0> {
};
+// As a high level description, an indirect goto takes the indirect_id of an
+// indirect entry as a parameter, and jumps to that location.
+//
+// In more detail: in order to preserve split-edge form, an intermediate target
+// entry consisting of a goto to the final indirect entry is inserted on
+// each possible indirect goto -> indirect entry edge. These target entries are
+// accessible through successors_.
+//
+// Byte offsets of all possible indirect targets are stored in the offsets_
+// array and are looked up at runtime.
+class IndirectGotoInstr : public TemplateInstruction<1> {
+ public:
+ IndirectGotoInstr(GrowableObjectArray* offsets,
Florian Schneider 2014/10/01 17:04:13 Can this be NULL? If not, just pass a const Growab
jgruber1 2014/10/03 18:59:51 No, but it is modified in SetOffsetCount() and Set
+ Value* offset_from_start)
+ : offset_from_start_(offset_from_start),
+ offsets_(*offsets) {
+ inputs_[0] = offset_from_start_;
Vyacheslav Egorov (Google) 2014/10/01 20:13:21 please add a comment explaining why you can't SetI
jgruber1 2014/10/03 18:59:51 Done, changed to SetInputAt().
+ offset_from_start_->set_instruction(this);
+ offset_from_start_->set_use_index(0);
+ }
+
+ DECLARE_INSTRUCTION(IndirectGoto)
+
+ virtual intptr_t ArgumentCount() const { return 0; }
+
+ void AddSuccessor(TargetEntryInstr* successor) {
+ ASSERT(successor->next()->IsGoto());
+ ASSERT(successor->next()->AsGoto()->successor()->IsIndirectEntry());
+ successors_.Add(successor);
+ }
+
+ virtual intptr_t SuccessorCount() const { return successors_.length(); }
+ virtual TargetEntryInstr* SuccessorAt(intptr_t index) const {
+ ASSERT(index < SuccessorCount());
+ return successors_[index];
+ }
+
+ virtual bool CanDeoptimize() const { return false; }
+ virtual bool CanBecomeDeoptimizationTarget() const { return false; }
+
+ virtual EffectSet Effects() const { return EffectSet::None(); }
+
+ virtual void PrintTo(BufferFormatter* f) const;
+
+ virtual bool MayThrow() const { return false; }
+
+ const GrowableObjectArray& offsets() const { return offsets_; }
+ void SetOffsetCount(Isolate* isolate, intptr_t count) {
+ if (offsets_.Capacity() < count) {
+ offsets_.Grow(count, Heap::kOld);
+ }
+ if (offsets_.Length() < count) {
+ offsets_.SetLength(count);
+ }
+ }
+ void SetOffsetAt(Isolate* isolate, intptr_t index, intptr_t offset) {
+ offsets_.SetAt(index, Smi::ZoneHandle(isolate, Smi::New(offset)));
+ }
+
+ private:
+ Value* offset_from_start_;
Florian Schneider 2014/10/02 11:58:12 Remove this member. SetInputAt(0,...) already stor
jgruber1 2014/10/03 18:59:51 Done.
+
+ GrowableArray<TargetEntryInstr*> successors_;
+ GrowableObjectArray& offsets_;
+};
+
+
class ComparisonInstr : public TemplateDefinition<2> {
public:
Value* left() const { return inputs_[0]; }
@@ -3767,6 +3878,71 @@ class LoadIndexedInstr : public TemplateDefinition<2> {
};
+// Loads the specified number of code units from the given string, packing
+// multiple code units into a single datatype. In essence, this is a specialized
+// version of LoadIndexedInstr which accepts only string targets may load
+// multiple elements at once. The result datatype differs depending on the
+// string type, element count, and architecture; if possible, the result is
+// packed into a Smi, falling back to a Mint otherwise.
+// TODO(jgruber): Add support for loading into UnboxedInt32x4.
+class LoadCodeUnitsInstr : public TemplateDefinition<2> {
+ public:
+ LoadCodeUnitsInstr(Value* array,
+ Value* index,
+ intptr_t index_scale,
+ intptr_t element_count,
+ intptr_t class_id,
+ intptr_t deopt_id,
+ intptr_t token_pos)
+ : index_scale_(index_scale),
+ class_id_(class_id),
+ token_pos_(token_pos),
+ element_count_(element_count) {
+ ASSERT(class_id == kOneByteStringCid || class_id == kTwoByteStringCid);
+ SetInputAt(0, array);
+ SetInputAt(1, index);
+ deopt_id_ = deopt_id;
Vyacheslav Egorov (Google) 2014/10/01 20:13:21 I don't think it can deoptimize.
jgruber1 2014/10/03 18:59:51 Done.
+ }
+
+ intptr_t token_pos() const { return token_pos_; }
+
+ DECLARE_INSTRUCTION(LoadCodeUnits)
+ virtual CompileType ComputeType() const;
+
+ bool IsExternal() const {
+ return array()->definition()->representation() == kUntagged;
+ }
+
+ Value* array() const { return inputs_[0]; }
+ Value* index() const { return inputs_[1]; }
+ intptr_t index_scale() const { return index_scale_; }
+ intptr_t class_id() const { return class_id_; }
+ intptr_t element_count() const { return element_count_; }
+
+ virtual bool CanDeoptimize() const {
+ return deopt_id_ != Isolate::kNoDeoptId;
+ }
+
+ virtual Representation representation() const;
+ virtual void InferRange(RangeAnalysis* analysis, Range* range);
+
+ virtual bool AllowsCSE() const { return false; }
+ virtual EffectSet Effects() const { return EffectSet::None(); }
+ virtual EffectSet Dependencies() const { return EffectSet::All(); }
+ virtual bool AttributesEqual(Instruction* other) const;
+
+ virtual bool MayThrow() const { return false; }
+
+ private:
+ const intptr_t index_scale_;
+ const intptr_t class_id_;
+ const intptr_t token_pos_;
+ const intptr_t element_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(LoadCodeUnitsInstr);
+};
+
+
class StringFromCharCodeInstr : public TemplateDefinition<1> {
public:
StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) {
@@ -4995,6 +5171,67 @@ class MathUnaryInstr : public TemplateDefinition<1> {
};
+// Calls into the runtime and performs a case-insensitive comparison of the
+// UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at
+// str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length].
+//
+// TODO(jgruber): Remove this once (if) functions inherited from unibrow
+// are moved to dart code.
+class CaseInsensitiveCompareUC16Instr : public TemplateDefinition<4> {
+ public:
+ CaseInsensitiveCompareUC16Instr(
+ Value* str,
+ Value* lhs_index,
+ Value* rhs_index,
+ Value* length,
+ intptr_t cid,
+ intptr_t deopt_id)
+ : cid_(cid) {
+ ASSERT(cid == kTwoByteStringCid || cid == kExternalTwoByteStringCid);
+ ASSERT(index_scale() == 2);
+ SetInputAt(0, str);
+ SetInputAt(1, lhs_index);
+ SetInputAt(2, rhs_index);
+ SetInputAt(3, length);
+ deopt_id_ = deopt_id;
Florian Schneider 2014/10/01 17:04:13 Not needed, since it can't deoptimize and also can
jgruber1 2014/10/03 18:59:51 Done.
+ }
+
+ Value* str() const { return inputs_[0]; }
+ Value* lhs_index() const { return inputs_[1]; }
+ Value* rhs_index() const { return inputs_[2]; }
+ Value* length() const { return inputs_[3]; }
+
+ const RuntimeEntry& TargetFunction() const;
+ bool IsExternal() const { return cid_ == kExternalTwoByteStringCid; }
+ intptr_t class_id() const { return cid_; }
+ intptr_t index_scale() const { return Instance::ElementSizeFor(cid_); }
+
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+ virtual bool CanDeoptimize() const { return false; }
+
+ virtual Representation representation() const {
+ return kTagged;
+ }
+
+ DECLARE_INSTRUCTION(CaseInsensitiveCompareUC16)
+ virtual CompileType ComputeType() const;
+
+ virtual bool AllowsCSE() const { return true; }
+ virtual EffectSet Effects() const { return EffectSet::None(); }
+ virtual EffectSet Dependencies() const { return EffectSet::None(); }
+
+ virtual bool MayThrow() const { return false; }
+
+ Definition* Canonicalize(FlowGraph* flow_graph);
+
+ private:
+ const intptr_t cid_;
+
+ DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareUC16Instr);
+};
+
+
// Represents Math's static min and max functions.
class MathMinMaxInstr : public TemplateDefinition<2> {
public:

Powered by Google App Engine
This is Rietveld 408576698