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

Side by Side Diff: runtime/vm/intermediate_language.h

Issue 10908091: Remove classes Computation and BindInstr. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/il_printer.cc ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_
6 #define VM_INTERMEDIATE_LANGUAGE_H_ 6 #define VM_INTERMEDIATE_LANGUAGE_H_
7 7
8 #include "vm/allocation.h" 8 #include "vm/allocation.h"
9 #include "vm/ast.h" 9 #include "vm/ast.h"
10 #include "vm/growable_array.h" 10 #include "vm/growable_array.h"
11 #include "vm/handles_impl.h" 11 #include "vm/handles_impl.h"
12 #include "vm/locations.h" 12 #include "vm/locations.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 14
15 namespace dart { 15 namespace dart {
16 16
17 class BindInstr;
18 class BitVector; 17 class BitVector;
19 class BlockEntryInstr; 18 class BlockEntryInstr;
20 class BufferFormatter; 19 class BufferFormatter;
21 class ComparisonComp; 20 class ComparisonInstr;
22 class ConstantComp;
23 class Computation;
24 class ControlInstruction; 21 class ControlInstruction;
25 class Definition; 22 class Definition;
26 class Environment; 23 class Environment;
27 class FlowGraphCompiler; 24 class FlowGraphCompiler;
28 class FlowGraphVisitor; 25 class FlowGraphVisitor;
29 class Instruction; 26 class Instruction;
30 class LocalVariable; 27 class LocalVariable;
31 28
32 29
33 // TODO(srdjan): Add _ByteArrayBase, get:length. 30 // TODO(srdjan): Add _ByteArrayBase, get:length.
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 // Instructions. 175 // Instructions.
179 176
180 // M is a single argument macro. It is applied to each concrete instruction 177 // M is a single argument macro. It is applied to each concrete instruction
181 // type name. The concrete instruction classes are the name with Instr 178 // type name. The concrete instruction classes are the name with Instr
182 // concatenated. 179 // concatenated.
183 #define FOR_EACH_INSTRUCTION(M) \ 180 #define FOR_EACH_INSTRUCTION(M) \
184 M(GraphEntry) \ 181 M(GraphEntry) \
185 M(JoinEntry) \ 182 M(JoinEntry) \
186 M(TargetEntry) \ 183 M(TargetEntry) \
187 M(Phi) \ 184 M(Phi) \
188 M(Bind) \
189 M(Parameter) \ 185 M(Parameter) \
190 M(ParallelMove) \ 186 M(ParallelMove) \
191 M(PushArgument) \ 187 M(PushArgument) \
192 M(Return) \ 188 M(Return) \
193 M(Throw) \ 189 M(Throw) \
194 M(ReThrow) \ 190 M(ReThrow) \
195 M(Goto) \ 191 M(Goto) \
196 M(Branch) \ 192 M(Branch) \
193 M(AssertAssignable) \
194 M(AssertBoolean) \
195 M(ArgumentDefinitionTest) \
196 M(CurrentContext) \
197 M(StoreContext) \
198 M(ClosureCall) \
199 M(InstanceCall) \
200 M(PolymorphicInstanceCall) \
201 M(StaticCall) \
202 M(LoadLocal) \
203 M(StoreLocal) \
204 M(StrictCompare) \
205 M(EqualityCompare) \
206 M(RelationalOp) \
207 M(NativeCall) \
208 M(LoadIndexed) \
209 M(StoreIndexed) \
210 M(LoadInstanceField) \
211 M(StoreInstanceField) \
212 M(LoadStaticField) \
213 M(StoreStaticField) \
214 M(BooleanNegate) \
215 M(InstanceOf) \
216 M(CreateArray) \
217 M(CreateClosure) \
218 M(AllocateObject) \
219 M(AllocateObjectWithBoundsCheck) \
220 M(LoadVMField) \
221 M(StoreVMField) \
222 M(InstantiateTypeArguments) \
223 M(ExtractConstructorTypeArguments) \
224 M(ExtractConstructorInstantiator) \
225 M(AllocateContext) \
226 M(ChainContext) \
227 M(CloneContext) \
228 M(CatchEntry) \
229 M(BinarySmiOp) \
230 M(BinaryMintOp) \
231 M(UnarySmiOp) \
232 M(NumberNegate) \
233 M(CheckStackOverflow) \
234 M(DoubleToDouble) \
235 M(SmiToDouble) \
236 M(CheckClass) \
237 M(CheckSmi) \
238 M(Constant) \
239 M(CheckEitherNonSmi) \
240 M(UnboxedDoubleBinaryOp) \
241 M(UnboxDouble) \
242 M(BoxDouble) \
243 M(CheckArrayBound) \
197 244
198 245
199 #define FORWARD_DECLARATION(type) class type##Instr; 246 #define FORWARD_DECLARATION(type) class type##Instr;
200 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) 247 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
201 #undef FORWARD_DECLARATION 248 #undef FORWARD_DECLARATION
202 249
203 250
204 // Functions required in all concrete instruction classes. 251 // Functions required in all concrete instruction classes.
205 #define DECLARE_INSTRUCTION(type) \ 252 #define DECLARE_INSTRUCTION(type) \
253 virtual Tag tag() const { return k##type; } \
206 virtual void Accept(FlowGraphVisitor* visitor); \ 254 virtual void Accept(FlowGraphVisitor* visitor); \
207 virtual type##Instr* As##type() { return this; } \ 255 virtual type##Instr* As##type() { return this; } \
208 virtual const char* DebugName() const { return #type; } \ 256 virtual const char* DebugName() const { return #type; } \
209 virtual void PrintTo(BufferFormatter* f) const; \ 257 virtual LocationSummary* MakeLocationSummary() const; \
210 virtual void PrintToVisualizer(BufferFormatter* f) const; 258 virtual void EmitNativeCode(FlowGraphCompiler* compiler); \
211 259
212 260
213 class Instruction : public ZoneAllocated { 261 class Instruction : public ZoneAllocated {
214 public: 262 public:
263 #define DECLARE_TAG(type) k##type,
264 enum Tag {
265 FOR_EACH_INSTRUCTION(DECLARE_TAG)
266 };
267 #undef DECLARE_TAG
268
215 Instruction() 269 Instruction()
216 : lifetime_position_(-1), previous_(NULL), next_(NULL), env_(NULL) { } 270 : deopt_id_(Isolate::Current()->GetNextDeoptId()),
271 lifetime_position_(-1),
272 previous_(NULL),
273 next_(NULL),
274 env_(NULL) { }
275
276 virtual Tag tag() const = 0;
277
278 intptr_t deopt_id() const { return deopt_id_; }
217 279
218 bool IsBlockEntry() { return (AsBlockEntry() != NULL); } 280 bool IsBlockEntry() { return (AsBlockEntry() != NULL); }
219 virtual BlockEntryInstr* AsBlockEntry() { return NULL; } 281 virtual BlockEntryInstr* AsBlockEntry() { return NULL; }
220 282
221 bool IsDefinition() { return (AsDefinition() != NULL); } 283 bool IsDefinition() { return (AsDefinition() != NULL); }
222 virtual Definition* AsDefinition() { return NULL; } 284 virtual Definition* AsDefinition() { return NULL; }
223 285
224 bool IsControl() { return (AsControl() != NULL); } 286 bool IsControl() { return (AsControl() != NULL); }
225 virtual ControlInstruction* AsControl() { return NULL; } 287 virtual ControlInstruction* AsControl() { return NULL; }
226 288
227 virtual intptr_t InputCount() const = 0; 289 virtual intptr_t InputCount() const = 0;
228 virtual Value* InputAt(intptr_t i) const = 0; 290 virtual Value* InputAt(intptr_t i) const = 0;
229 virtual void SetInputAt(intptr_t i, Value* value) = 0; 291 virtual void SetInputAt(intptr_t i, Value* value) = 0;
230 292
231 // Call instructions override this function and return the 293 // Call instructions override this function and return the number of
232 // number of pushed arguments. 294 // pushed arguments.
233 virtual intptr_t ArgumentCount() const = 0; 295 virtual intptr_t ArgumentCount() const = 0;
234 296
235 // Returns true, if this instruction can deoptimize. 297 // Returns true, if this instruction can deoptimize.
236 virtual bool CanDeoptimize() const = 0; 298 virtual bool CanDeoptimize() const = 0;
237 299
238 // Visiting support. 300 // Visiting support.
239 virtual void Accept(FlowGraphVisitor* visitor) = 0; 301 virtual void Accept(FlowGraphVisitor* visitor) = 0;
240 302
241 Instruction* previous() const { return previous_; } 303 Instruction* previous() const { return previous_; }
242 void set_previous(Instruction* instr) { 304 void set_previous(Instruction* instr) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 intptr_t fixed_parameter_count) { 354 intptr_t fixed_parameter_count) {
293 // Never called for instructions except block entries and branches. 355 // Never called for instructions except block entries and branches.
294 UNREACHABLE(); 356 UNREACHABLE();
295 } 357 }
296 358
297 // Mutate assigned_vars to add the local variable index for all 359 // Mutate assigned_vars to add the local variable index for all
298 // frame-allocated locals assigned to by the instruction. 360 // frame-allocated locals assigned to by the instruction.
299 virtual void RecordAssignedVars(BitVector* assigned_vars, 361 virtual void RecordAssignedVars(BitVector* assigned_vars,
300 intptr_t fixed_parameter_count); 362 intptr_t fixed_parameter_count);
301 363
364 virtual const char* DebugName() const = 0;
365
302 // Printing support. 366 // Printing support.
303 virtual void PrintTo(BufferFormatter* f) const = 0; 367 virtual void PrintTo(BufferFormatter* f) const = 0;
304 virtual void PrintToVisualizer(BufferFormatter* f) const = 0; 368 virtual void PrintToVisualizer(BufferFormatter* f) const = 0;
305 369
306 #define INSTRUCTION_TYPE_CHECK(type) \ 370 #define INSTRUCTION_TYPE_CHECK(type) \
307 bool Is##type() { return (As##type() != NULL); } \ 371 bool Is##type() { return (As##type() != NULL); } \
308 virtual type##Instr* As##type() { return NULL; } 372 virtual type##Instr* As##type() { return NULL; }
309 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) 373 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
310 #undef INSTRUCTION_TYPE_CHECK 374 #undef INSTRUCTION_TYPE_CHECK
311 375
312 // Returns structure describing location constraints required 376 // Returns structure describing location constraints required
313 // to emit native code for this instruction. 377 // to emit native code for this instruction.
314 virtual LocationSummary* locs() { 378 virtual LocationSummary* locs() {
315 // TODO(vegorov): This should be pure virtual method. 379 // TODO(vegorov): This should be pure virtual method.
316 // However we are temporary using NULL for instructions that 380 // However we are temporary using NULL for instructions that
317 // were not converted to the location based code generation yet. 381 // were not converted to the location based code generation yet.
318 return NULL; 382 return NULL;
319 } 383 }
320 384
385 virtual LocationSummary* MakeLocationSummary() const = 0;
386
387 static LocationSummary* MakeCallSummary();
388
321 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 389 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
322 UNIMPLEMENTED(); 390 UNIMPLEMENTED();
323 } 391 }
324 392
325 Environment* env() const { return env_; } 393 Environment* env() const { return env_; }
326 void set_env(Environment* env) { env_ = env; } 394 void set_env(Environment* env) { env_ = env; }
327 395
328 intptr_t lifetime_position() const { return lifetime_position_; } 396 intptr_t lifetime_position() const { return lifetime_position_; }
329 void set_lifetime_position(intptr_t pos) { 397 void set_lifetime_position(intptr_t pos) {
330 lifetime_position_ = pos; 398 lifetime_position_ = pos;
(...skipping 14 matching lines...) Expand all
345 } 413 }
346 414
347 // Returns deoptimization id that corresponds to the deoptimization target 415 // Returns deoptimization id that corresponds to the deoptimization target
348 // that input operands conversions inserted for this instruction can jump 416 // that input operands conversions inserted for this instruction can jump
349 // to. 417 // to.
350 virtual intptr_t DeoptimizationTarget() const { 418 virtual intptr_t DeoptimizationTarget() const {
351 UNREACHABLE(); 419 UNREACHABLE();
352 return Isolate::kNoDeoptId; 420 return Isolate::kNoDeoptId;
353 } 421 }
354 422
423 protected:
424 // Fetch deopt id without checking if this computation can deoptimize.
425 intptr_t GetDeoptId() const {
426 return deopt_id_;
427 }
428
355 private: 429 private:
356 friend class Definition; // Needed for InsertBefore, InsertAfter. 430 friend class Definition; // Needed for InsertBefore, InsertAfter.
357 431
432 // Classes that set deopt_id_.
433 friend class UnboxDoubleInstr;
434 friend class UnboxedDoubleBinaryOpInstr;
435 friend class CheckClassInstr;
436 friend class CheckSmiInstr;
437 friend class CheckNonSmiInstr;
438 friend class CheckArrayBoundInstr;
439 friend class CheckEitherNonSmiInstr;
440
441 intptr_t deopt_id_;
358 intptr_t lifetime_position_; // Position used by register allocator. 442 intptr_t lifetime_position_; // Position used by register allocator.
359 Instruction* previous_; 443 Instruction* previous_;
360 Instruction* next_; 444 Instruction* next_;
361 Environment* env_; 445 Environment* env_;
362 DISALLOW_COPY_AND_ASSIGN(Instruction); 446 DISALLOW_COPY_AND_ASSIGN(Instruction);
363 }; 447 };
364 448
365 449
366 template<intptr_t N> 450 template<intptr_t N>
367 class TemplateInstruction: public Instruction { 451 class TemplateInstruction: public Instruction {
368 public: 452 public:
369 TemplateInstruction<N>() : locs_(NULL) { } 453 TemplateInstruction<N>() : locs_(NULL) { }
370 454
371 virtual intptr_t InputCount() const { return N; } 455 virtual intptr_t InputCount() const { return N; }
372 virtual Value* InputAt(intptr_t i) const { return inputs_[i]; } 456 virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
373 virtual void SetInputAt(intptr_t i, Value* value) { 457 virtual void SetInputAt(intptr_t i, Value* value) {
374 ASSERT(value != NULL); 458 ASSERT(value != NULL);
375 inputs_[i] = value; 459 inputs_[i] = value;
376 } 460 }
377 461
378 virtual LocationSummary* locs() { 462 virtual LocationSummary* locs() {
379 if (locs_ == NULL) { 463 if (locs_ == NULL) {
380 locs_ = MakeLocationSummary(); 464 locs_ = MakeLocationSummary();
381 } 465 }
382 return locs_; 466 return locs_;
383 } 467 }
384 468
385 virtual LocationSummary* MakeLocationSummary() const = 0;
386
387 protected: 469 protected:
388 EmbeddedArray<Value*, N> inputs_; 470 EmbeddedArray<Value*, N> inputs_;
389 471
390 private: 472 private:
391 LocationSummary* locs_; 473 LocationSummary* locs_;
392 }; 474 };
393 475
394 476
395 class MoveOperands : public ZoneAllocated { 477 class MoveOperands : public ZoneAllocated {
396 public: 478 public:
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 return move; 548 return move;
467 } 549 }
468 550
469 MoveOperands* MoveOperandsAt(intptr_t index) const { return moves_[index]; } 551 MoveOperands* MoveOperandsAt(intptr_t index) const { return moves_[index]; }
470 552
471 void SetSrcSlotAt(intptr_t index, const Location& loc); 553 void SetSrcSlotAt(intptr_t index, const Location& loc);
472 void SetDestSlotAt(intptr_t index, const Location& loc); 554 void SetDestSlotAt(intptr_t index, const Location& loc);
473 555
474 intptr_t NumMoves() const { return moves_.length(); } 556 intptr_t NumMoves() const { return moves_.length(); }
475 557
476 LocationSummary* MakeLocationSummary() const { return NULL; } 558 virtual void PrintTo(BufferFormatter* f) const;
477 559 virtual void PrintToVisualizer(BufferFormatter* f) const;
478 void EmitNativeCode(FlowGraphCompiler* compiler) { UNREACHABLE(); }
479 560
480 private: 561 private:
481 GrowableArray<MoveOperands*> moves_; // Elements cannot be null. 562 GrowableArray<MoveOperands*> moves_; // Elements cannot be null.
482 563
483 DISALLOW_COPY_AND_ASSIGN(ParallelMoveInstr); 564 DISALLOW_COPY_AND_ASSIGN(ParallelMoveInstr);
484 }; 565 };
485 566
486 567
487 // Basic block entries are administrative nodes. There is a distinguished 568 // Basic block entries are administrative nodes. There is a distinguished
488 // graph entry with no predecessor. Joins are the only nodes with multiple 569 // graph entry with no predecessor. Joins are the only nodes with multiple
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 void Advance() { 688 void Advance() {
608 ASSERT(!Done()); 689 ASSERT(!Done());
609 current_ = current_->next(); 690 current_ = current_->next();
610 } 691 }
611 692
612 bool Done() const { return current_ == NULL; } 693 bool Done() const { return current_ == NULL; }
613 694
614 // Removes 'current_' from graph and sets 'current_' to previous instruction. 695 // Removes 'current_' from graph and sets 'current_' to previous instruction.
615 void RemoveCurrentFromGraph(); 696 void RemoveCurrentFromGraph();
616 697
698 // Inserts replaces 'current_', which must be a definition, with another
699 // definition. The new definition becomes 'current_'.
700 void ReplaceCurrentWith(Definition* other);
701
617 Instruction* Current() const { return current_; } 702 Instruction* Current() const { return current_; }
618 703
619 private: 704 private:
620 BlockEntryInstr* block_entry_; 705 BlockEntryInstr* block_entry_;
621 Instruction* current_; 706 Instruction* current_;
622 }; 707 };
623 708
624 709
625 class BackwardInstructionIterator : public ValueObject { 710 class BackwardInstructionIterator : public ValueObject {
626 public: 711 public:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 intptr_t variable_count, 754 intptr_t variable_count,
670 intptr_t fixed_parameter_count); 755 intptr_t fixed_parameter_count);
671 756
672 void AddCatchEntry(TargetEntryInstr* entry) { catch_entries_.Add(entry); } 757 void AddCatchEntry(TargetEntryInstr* entry) { catch_entries_.Add(entry); }
673 758
674 virtual void PrepareEntry(FlowGraphCompiler* compiler); 759 virtual void PrepareEntry(FlowGraphCompiler* compiler);
675 760
676 Environment* start_env() const { return start_env_; } 761 Environment* start_env() const { return start_env_; }
677 void set_start_env(Environment* env) { start_env_ = env; } 762 void set_start_env(Environment* env) { start_env_ = env; }
678 763
679 Definition* constant_null() const { return constant_null_; } 764 ConstantInstr* constant_null() const { return constant_null_; }
680 765
681 intptr_t spill_slot_count() const { return spill_slot_count_; } 766 intptr_t spill_slot_count() const { return spill_slot_count_; }
682 void set_spill_slot_count(intptr_t count) { 767 void set_spill_slot_count(intptr_t count) {
683 ASSERT(count >= 0); 768 ASSERT(count >= 0);
684 spill_slot_count_ = count; 769 spill_slot_count_ = count;
685 } 770 }
686 771
687 TargetEntryInstr* normal_entry() const { return normal_entry_; } 772 TargetEntryInstr* normal_entry() const { return normal_entry_; }
688 773
774 virtual void PrintTo(BufferFormatter* f) const;
775 virtual void PrintToVisualizer(BufferFormatter* f) const;
776
689 private: 777 private:
690 TargetEntryInstr* normal_entry_; 778 TargetEntryInstr* normal_entry_;
691 GrowableArray<TargetEntryInstr*> catch_entries_; 779 GrowableArray<TargetEntryInstr*> catch_entries_;
692 Environment* start_env_; 780 Environment* start_env_;
693 Definition* constant_null_; 781 ConstantInstr* constant_null_;
694 intptr_t spill_slot_count_; 782 intptr_t spill_slot_count_;
695 783
696 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); 784 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr);
697 }; 785 };
698 786
699 787
700 class JoinEntryInstr : public BlockEntryInstr { 788 class JoinEntryInstr : public BlockEntryInstr {
701 public: 789 public:
702 explicit JoinEntryInstr(intptr_t try_index) 790 explicit JoinEntryInstr(intptr_t try_index)
703 : BlockEntryInstr(try_index), 791 : BlockEntryInstr(try_index),
(...skipping 16 matching lines...) Expand all
720 808
721 ZoneGrowableArray<PhiInstr*>* phis() const { return phis_; } 809 ZoneGrowableArray<PhiInstr*>* phis() const { return phis_; }
722 810
723 virtual void PrepareEntry(FlowGraphCompiler* compiler); 811 virtual void PrepareEntry(FlowGraphCompiler* compiler);
724 812
725 void InsertPhi(intptr_t var_index, intptr_t var_count); 813 void InsertPhi(intptr_t var_index, intptr_t var_count);
726 void RemoveDeadPhis(); 814 void RemoveDeadPhis();
727 815
728 intptr_t phi_count() const { return phi_count_; } 816 intptr_t phi_count() const { return phi_count_; }
729 817
818 virtual void PrintTo(BufferFormatter* f) const;
819 virtual void PrintToVisualizer(BufferFormatter* f) const;
820
730 private: 821 private:
731 GrowableArray<BlockEntryInstr*> predecessors_; 822 GrowableArray<BlockEntryInstr*> predecessors_;
732 ZoneGrowableArray<PhiInstr*>* phis_; 823 ZoneGrowableArray<PhiInstr*>* phis_;
733 intptr_t phi_count_; 824 intptr_t phi_count_;
734 825
735 DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr); 826 DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr);
736 }; 827 };
737 828
738 829
739 class TargetEntryInstr : public BlockEntryInstr { 830 class TargetEntryInstr : public BlockEntryInstr {
(...skipping 30 matching lines...) Expand all
770 861
771 // Returns try index for the try block to which this catch handler 862 // Returns try index for the try block to which this catch handler
772 // corresponds. 863 // corresponds.
773 intptr_t catch_try_index() const { 864 intptr_t catch_try_index() const {
774 ASSERT(IsCatchEntry()); 865 ASSERT(IsCatchEntry());
775 return catch_try_index_; 866 return catch_try_index_;
776 } 867 }
777 868
778 virtual void PrepareEntry(FlowGraphCompiler* compiler); 869 virtual void PrepareEntry(FlowGraphCompiler* compiler);
779 870
871 virtual void PrintTo(BufferFormatter* f) const;
872 virtual void PrintToVisualizer(BufferFormatter* f) const;
873
780 private: 874 private:
781 BlockEntryInstr* predecessor_; 875 BlockEntryInstr* predecessor_;
782 const intptr_t catch_try_index_; 876 const intptr_t catch_try_index_;
783 877
784 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); 878 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr);
785 }; 879 };
786 880
787 881
788 // Abstract super-class of all instructions that define a value (Bind, Phi). 882 // Abstract super-class of all instructions that define a value (Bind, Phi).
789 class Definition : public Instruction { 883 class Definition : public Instruction {
790 public: 884 public:
791 enum UseKind { kEffect, kValue }; 885 enum UseKind { kEffect, kValue };
792 886
793 Definition() 887 Definition()
794 : temp_index_(-1), 888 : temp_index_(-1),
795 ssa_temp_index_(-1), 889 ssa_temp_index_(-1),
796 propagated_type_(AbstractType::Handle()), 890 propagated_type_(AbstractType::Handle()),
797 propagated_cid_(kIllegalCid), 891 propagated_cid_(kIllegalCid),
798 input_use_list_(NULL), 892 input_use_list_(NULL),
799 env_use_list_(NULL), 893 env_use_list_(NULL),
800 use_kind_(kValue) { // Phis and parameters rely on this default. 894 use_kind_(kValue) { // Phis and parameters rely on this default.
801 } 895 }
802 896
803 virtual Definition* AsDefinition() { return this; } 897 virtual Definition* AsDefinition() { return this; }
804 898
899 bool IsComparison() { return (AsComparison() != NULL); }
900 virtual ComparisonInstr* AsComparison() { return NULL; }
901
902 // Overridden by definitions that push arguments.
903 virtual intptr_t ArgumentCount() const { return 0; }
904
805 intptr_t temp_index() const { return temp_index_; } 905 intptr_t temp_index() const { return temp_index_; }
806 void set_temp_index(intptr_t index) { temp_index_ = index; } 906 void set_temp_index(intptr_t index) { temp_index_ = index; }
807 907
808 intptr_t ssa_temp_index() const { return ssa_temp_index_; } 908 intptr_t ssa_temp_index() const { return ssa_temp_index_; }
809 void set_ssa_temp_index(intptr_t index) { 909 void set_ssa_temp_index(intptr_t index) {
810 ASSERT(index >= 0); 910 ASSERT(index >= 0);
811 ASSERT(is_used()); 911 ASSERT(is_used());
812 ssa_temp_index_ = index; 912 ssa_temp_index_ = index;
813 } 913 }
814 bool HasSSATemp() const { return ssa_temp_index_ >= 0; } 914 bool HasSSATemp() const { return ssa_temp_index_ >= 0; }
815 915
816 bool is_used() const { return (use_kind_ != kEffect); } 916 bool is_used() const { return (use_kind_ != kEffect); }
817 void set_use_kind(UseKind kind) { use_kind_ = kind; } 917 void set_use_kind(UseKind kind) { use_kind_ = kind; }
818 918
819 // Compile time type of the definition, which may be requested before type 919 // Compile time type of the definition, which may be requested before type
820 // propagation during graph building. 920 // propagation during graph building.
821 virtual RawAbstractType* CompileType() const = 0; 921 virtual RawAbstractType* CompileType() const = 0;
822 922
923 virtual intptr_t ResultCid() const = 0;
924
823 bool HasPropagatedType() const { 925 bool HasPropagatedType() const {
824 return !propagated_type_.IsNull(); 926 return !propagated_type_.IsNull();
825 } 927 }
826 RawAbstractType* PropagatedType() const { 928 RawAbstractType* PropagatedType() const {
827 ASSERT(HasPropagatedType()); 929 ASSERT(HasPropagatedType());
828 return propagated_type_.raw(); 930 return propagated_type_.raw();
829 } 931 }
830 // Returns true if the propagated type has changed. 932 // Returns true if the propagated type has changed.
831 bool SetPropagatedType(const AbstractType& propagated_type) { 933 bool SetPropagatedType(const AbstractType& propagated_type) {
832 if (propagated_type.IsNull()) { 934 if (propagated_type.IsNull()) {
833 // Not a typed definition, e.g. access to a VM field. 935 // Not a typed definition, e.g. access to a VM field.
834 return false; 936 return false;
835 } 937 }
836 const bool changed = 938 const bool changed =
837 propagated_type_.IsNull() || !propagated_type.Equals(propagated_type_); 939 propagated_type_.IsNull() || !propagated_type.Equals(propagated_type_);
838 propagated_type_ = propagated_type.raw(); 940 propagated_type_ = propagated_type.raw();
839 return changed; 941 return changed;
840 } 942 }
841 943
842 bool has_propagated_cid() const { return propagated_cid_ != kIllegalCid; } 944 bool has_propagated_cid() const { return propagated_cid_ != kIllegalCid; }
843 intptr_t propagated_cid() const { return propagated_cid_; } 945 intptr_t propagated_cid() const { return propagated_cid_; }
946
844 // May compute and set propagated cid. 947 // May compute and set propagated cid.
845 virtual intptr_t GetPropagatedCid() = 0; 948 virtual intptr_t GetPropagatedCid();
846 949
847 // Returns true if the propagated cid has changed. 950 // Returns true if the propagated cid has changed.
848 bool SetPropagatedCid(intptr_t cid); 951 bool SetPropagatedCid(intptr_t cid);
849 952
953 // Returns true if the definition may have side effects.
954 // TODO(fschneider): Make this abstract and implement for all definitions
955 // instead of returning the safe default (true).
956 virtual bool HasSideEffect() const { return true; }
957
850 Value* input_use_list() { return input_use_list_; } 958 Value* input_use_list() { return input_use_list_; }
851 void set_input_use_list(Value* head) { input_use_list_ = head; } 959 void set_input_use_list(Value* head) { input_use_list_ = head; }
852 960
853 Value* env_use_list() { return env_use_list_; } 961 Value* env_use_list() { return env_use_list_; }
854 void set_env_use_list(Value* head) { env_use_list_ = head; } 962 void set_env_use_list(Value* head) { env_use_list_ = head; }
855 963
964 // Returns a replacement for the definition or NULL if the definition can
965 // be eliminated. By default returns the definition (input parameter)
966 // which means no change.
967 virtual Definition* Canonicalize();
968
856 // Replace uses of this definition with uses of other definition or value. 969 // Replace uses of this definition with uses of other definition or value.
857 // Precondition: use lists must be properly calculated. 970 // Precondition: use lists must be properly calculated.
858 // Postcondition: use lists and use values are still valid. 971 // Postcondition: use lists and use values are still valid.
859 void ReplaceUsesWith(Definition* other); 972 void ReplaceUsesWith(Definition* other);
860 973
974 // Replace this definition and all uses with another definition. If
975 // replacing during iteration, pass the iterator so that the instruction
976 // can be replaced without affecting iteration order, otherwise pass a
977 // NULL iterator.
978 void ReplaceWith(Definition* other, ForwardInstructionIterator* iterator);
979
861 // Insert this definition before 'next'. 980 // Insert this definition before 'next'.
862 void InsertBefore(Instruction* next); 981 void InsertBefore(Instruction* next);
863 982
864 // Insert this definition after 'prev'. 983 // Insert this definition after 'prev'.
865 void InsertAfter(Instruction* prev); 984 void InsertAfter(Instruction* prev);
866 985
867 // If this definition is a bind of a constant return it. 986 // Compares two definitions. Returns true, iff:
868 // Otherwise return NULL. 987 // 1. They have the same tag.
869 ConstantComp* AsConstant(); 988 // 2. All input operands are Equals.
989 // 3. They satisfy AttributesEqual.
990 bool Equals(Definition* other) const;
991
992 // Compare attributes of a definition (except input operands and tag).
993 // All definition that participate in CSE have to override this function.
994 // This function can assume that the argument has the same type as this.
995 virtual bool AttributesEqual(Definition* other) const {
996 UNREACHABLE();
997 return false;
998 }
999
1000 // Returns a hash code for use with hash maps.
1001 virtual intptr_t Hashcode() const;
1002
1003 virtual void RecordAssignedVars(BitVector* assigned_vars,
1004 intptr_t fixed_parameter_count);
1005
1006 // Printing support. These functions are sometimes overridden for custom
1007 // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)".
1008 virtual void PrintTo(BufferFormatter* f) const;
1009 virtual void PrintOperandsTo(BufferFormatter* f) const;
1010 virtual void PrintToVisualizer(BufferFormatter* f) const;
870 1011
871 private: 1012 private:
872 intptr_t temp_index_; 1013 intptr_t temp_index_;
873 intptr_t ssa_temp_index_; 1014 intptr_t ssa_temp_index_;
874 // TODO(regis): GrowableArray<const AbstractType*> propagated_types_; 1015 // TODO(regis): GrowableArray<const AbstractType*> propagated_types_;
875 // For now: 1016 // For now:
876 AbstractType& propagated_type_; 1017 AbstractType& propagated_type_;
877 intptr_t propagated_cid_; 1018 intptr_t propagated_cid_;
878 Value* input_use_list_; 1019 Value* input_use_list_;
879 Value* env_use_list_; 1020 Value* env_use_list_;
880 UseKind use_kind_; 1021 UseKind use_kind_;
881 1022
882 DISALLOW_COPY_AND_ASSIGN(Definition); 1023 DISALLOW_COPY_AND_ASSIGN(Definition);
883 }; 1024 };
884 1025
885 1026
886 class BindInstr : public Definition {
887 public:
888 BindInstr(UseKind used, Computation* computation)
889 : computation_(computation) {
890 ASSERT(computation != NULL);
891 set_use_kind(used);
892 }
893
894 DECLARE_INSTRUCTION(Bind)
895
896 // Overridden functions from class Instruction.
897 virtual intptr_t ArgumentCount() const;
898 intptr_t InputCount() const;
899 Value* InputAt(intptr_t i) const;
900 void SetInputAt(intptr_t i, Value* value);
901 virtual bool CanDeoptimize() const;
902 virtual void RecordAssignedVars(BitVector* assigned_vars,
903 intptr_t fixed_parameter_count);
904 virtual LocationSummary* locs();
905 virtual void EmitNativeCode(FlowGraphCompiler* compiler);
906 virtual Representation RequiredInputRepresentation(intptr_t i) const;
907 virtual Representation representation() const;
908 virtual intptr_t DeoptimizationTarget() const;
909
910 Computation* computation() const { return computation_; }
911 void set_computation(Computation* value) { computation_ = value; }
912
913 // Overridden functions from class Definition.
914 virtual RawAbstractType* CompileType() const;
915 virtual intptr_t GetPropagatedCid();
916
917 // Other functions that forward to the computation.
918 intptr_t Hashcode() const;
919 bool Equals(BindInstr* other) const;
920
921 private:
922 Computation* computation_;
923
924 DISALLOW_COPY_AND_ASSIGN(BindInstr);
925 };
926
927
928 class PhiInstr : public Definition { 1027 class PhiInstr : public Definition {
929 public: 1028 public:
930 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs) 1029 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
931 : block_(block), 1030 : block_(block),
932 inputs_(num_inputs), 1031 inputs_(num_inputs),
933 is_alive_(false), 1032 is_alive_(false),
934 representation_(kTagged) { 1033 representation_(kTagged) {
935 for (intptr_t i = 0; i < num_inputs; ++i) { 1034 for (intptr_t i = 0; i < num_inputs; ++i) {
936 inputs_.Add(NULL); 1035 inputs_.Add(NULL);
937 } 1036 }
938 } 1037 }
939 1038
940 JoinEntryInstr* block() const { return block_; } 1039 JoinEntryInstr* block() const { return block_; }
941 1040
942 virtual RawAbstractType* CompileType() const; 1041 virtual RawAbstractType* CompileType() const;
943 virtual intptr_t GetPropagatedCid() { return propagated_cid(); } 1042 virtual intptr_t GetPropagatedCid();
944 1043
945 virtual intptr_t ArgumentCount() const { return 0; } 1044 virtual intptr_t ArgumentCount() const { return 0; }
946 1045
947 intptr_t InputCount() const { return inputs_.length(); } 1046 intptr_t InputCount() const { return inputs_.length(); }
948 1047
949 Value* InputAt(intptr_t i) const { return inputs_[i]; } 1048 Value* InputAt(intptr_t i) const { return inputs_[i]; }
950 1049
951 void SetInputAt(intptr_t i, Value* value) { inputs_[i] = value; } 1050 void SetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
952 1051
953 virtual bool CanDeoptimize() const { return false; } 1052 virtual bool CanDeoptimize() const { return false; }
(...skipping 10 matching lines...) Expand all
964 } 1063 }
965 1064
966 virtual Representation representation() const { 1065 virtual Representation representation() const {
967 return representation_; 1066 return representation_;
968 } 1067 }
969 1068
970 virtual void set_representation(Representation r) { 1069 virtual void set_representation(Representation r) {
971 representation_ = r; 1070 representation_ = r;
972 } 1071 }
973 1072
1073 virtual intptr_t Hashcode() const {
1074 UNREACHABLE();
1075 return 0;
1076 }
1077
1078 virtual intptr_t ResultCid() const {
1079 UNREACHABLE();
1080 return kIllegalCid;
1081 }
1082
974 DECLARE_INSTRUCTION(Phi) 1083 DECLARE_INSTRUCTION(Phi)
975 1084
1085 virtual void PrintTo(BufferFormatter* f) const;
1086 virtual void PrintToVisualizer(BufferFormatter* f) const;
1087
976 private: 1088 private:
977 JoinEntryInstr* block_; 1089 JoinEntryInstr* block_;
978 GrowableArray<Value*> inputs_; 1090 GrowableArray<Value*> inputs_;
979 bool is_alive_; 1091 bool is_alive_;
980 Representation representation_; 1092 Representation representation_;
981 1093
982 DISALLOW_COPY_AND_ASSIGN(PhiInstr); 1094 DISALLOW_COPY_AND_ASSIGN(PhiInstr);
983 }; 1095 };
984 1096
985 1097
986 class ParameterInstr : public Definition { 1098 class ParameterInstr : public Definition {
987 public: 1099 public:
988 explicit ParameterInstr(intptr_t index) : index_(index) { } 1100 explicit ParameterInstr(intptr_t index) : index_(index) { }
989 1101
990 DECLARE_INSTRUCTION(Parameter) 1102 DECLARE_INSTRUCTION(Parameter)
991 1103
992 intptr_t index() const { return index_; } 1104 intptr_t index() const { return index_; }
993 1105
994 // Compile type of the passed-in parameter. 1106 // Compile type of the passed-in parameter.
995 virtual RawAbstractType* CompileType() const; 1107 virtual RawAbstractType* CompileType() const;
1108
996 // No known propagated cid for parameters. 1109 // No known propagated cid for parameters.
997 virtual intptr_t GetPropagatedCid() { return propagated_cid(); } 1110 virtual intptr_t GetPropagatedCid();
998 1111
999 virtual intptr_t ArgumentCount() const { return 0; } 1112 virtual intptr_t ArgumentCount() const { return 0; }
1000 1113
1001 intptr_t InputCount() const { return 0; } 1114 intptr_t InputCount() const { return 0; }
1002 Value* InputAt(intptr_t i) const { 1115 Value* InputAt(intptr_t i) const {
1003 UNREACHABLE(); 1116 UNREACHABLE();
1004 return NULL; 1117 return NULL;
1005 } 1118 }
1006 void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } 1119 void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
1007 1120
1008 virtual bool CanDeoptimize() const { return false; } 1121 virtual bool CanDeoptimize() const { return false; }
1009 1122
1123 virtual intptr_t Hashcode() const {
1124 UNREACHABLE();
1125 return 0;
1126 }
1127
1128 virtual intptr_t ResultCid() const {
1129 UNREACHABLE();
1130 return kIllegalCid;
1131 }
1132
1133 virtual void PrintTo(BufferFormatter* f) const;
1134 virtual void PrintToVisualizer(BufferFormatter* f) const;
1135
1010 private: 1136 private:
1011 const intptr_t index_; 1137 const intptr_t index_;
1012 1138
1013 DISALLOW_COPY_AND_ASSIGN(ParameterInstr); 1139 DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
1014 }; 1140 };
1015 1141
1016 1142
1017 class PushArgumentInstr : public Definition { 1143 class PushArgumentInstr : public Definition {
1018 public: 1144 public:
1019 explicit PushArgumentInstr(Value* value) : value_(value), locs_(NULL) { 1145 explicit PushArgumentInstr(Value* value) : value_(value), locs_(NULL) {
1020 ASSERT(value != NULL); 1146 ASSERT(value != NULL);
1147 set_use_kind(kEffect); // Override the default.
1021 } 1148 }
1022 1149
1023 DECLARE_INSTRUCTION(PushArgument) 1150 DECLARE_INSTRUCTION(PushArgument)
1024 1151
1025 intptr_t InputCount() const { return 1; } 1152 intptr_t InputCount() const { return 1; }
1026 Value* InputAt(intptr_t i) const { 1153 Value* InputAt(intptr_t i) const {
1027 ASSERT(i == 0); 1154 ASSERT(i == 0);
1028 return value_; 1155 return value_;
1029 } 1156 }
1030 void SetInputAt(intptr_t i, Value* value) { 1157 void SetInputAt(intptr_t i, Value* value) {
1031 ASSERT(i == 0); 1158 ASSERT(i == 0);
1032 value_ = value; 1159 value_ = value;
1033 } 1160 }
1034 1161
1035 virtual intptr_t ArgumentCount() const { return 0; } 1162 virtual intptr_t ArgumentCount() const { return 0; }
1036 1163
1037 virtual RawAbstractType* CompileType() const; 1164 virtual RawAbstractType* CompileType() const;
1038 virtual intptr_t GetPropagatedCid() { return propagated_cid(); } 1165 virtual intptr_t GetPropagatedCid() { return propagated_cid(); }
Florian Schneider 2012/09/05 11:14:42 Move to .cc file as well?
1166 virtual intptr_t ResultCid() const { return kIllegalCid; }
Florian Schneider 2012/09/05 11:14:42 UNREACHABLE();
Kevin Millikin (Google) 2012/09/05 11:27:28 Oops, we can't. As is, this is called in the type
1039 1167
1040 Value* value() const { return value_; } 1168 Value* value() const { return value_; }
1041 1169
1042 virtual LocationSummary* locs() { 1170 virtual LocationSummary* locs() {
1043 if (locs_ == NULL) { 1171 if (locs_ == NULL) {
1044 locs_ = MakeLocationSummary(); 1172 locs_ = MakeLocationSummary();
1045 } 1173 }
1046 return locs_; 1174 return locs_;
1047 } 1175 }
1048 1176
1049 LocationSummary* MakeLocationSummary() const; 1177 virtual intptr_t Hashcode() const {
1050 1178 UNREACHABLE();
1051 virtual void EmitNativeCode(FlowGraphCompiler* compiler); 1179 return 0;
1180 }
1052 1181
1053 virtual bool CanDeoptimize() const { return false; } 1182 virtual bool CanDeoptimize() const { return false; }
1054 1183
1184 virtual void PrintTo(BufferFormatter* f) const;
1185 virtual void PrintToVisualizer(BufferFormatter* f) const;
1186
1055 private: 1187 private:
1056 Value* value_; 1188 Value* value_;
1057 LocationSummary* locs_; 1189 LocationSummary* locs_;
1058 1190
1059 DISALLOW_COPY_AND_ASSIGN(PushArgumentInstr); 1191 DISALLOW_COPY_AND_ASSIGN(PushArgumentInstr);
1060 }; 1192 };
1061 1193
1062 1194
1063 class ReturnInstr : public TemplateInstruction<1> { 1195 class ReturnInstr : public TemplateInstruction<1> {
1064 public: 1196 public:
1065 ReturnInstr(intptr_t token_pos, Value* value) 1197 ReturnInstr(intptr_t token_pos, Value* value)
1066 : deopt_id_(Isolate::Current()->GetNextDeoptId()), 1198 : token_pos_(token_pos) {
1067 token_pos_(token_pos) {
1068 ASSERT(value != NULL); 1199 ASSERT(value != NULL);
1069 inputs_[0] = value; 1200 inputs_[0] = value;
1070 } 1201 }
1071 1202
1072 DECLARE_INSTRUCTION(Return) 1203 DECLARE_INSTRUCTION(Return)
1073 1204
1074 virtual intptr_t ArgumentCount() const { return 0; } 1205 virtual intptr_t ArgumentCount() const { return 0; }
1075 1206
1076 intptr_t deopt_id() const { return deopt_id_; }
1077 intptr_t token_pos() const { return token_pos_; } 1207 intptr_t token_pos() const { return token_pos_; }
1078 Value* value() const { return inputs_[0]; } 1208 Value* value() const { return inputs_[0]; }
1079 1209
1080 virtual LocationSummary* MakeLocationSummary() const;
1081
1082 virtual void EmitNativeCode(FlowGraphCompiler* compiler);
1083
1084 virtual bool CanDeoptimize() const { return false; } 1210 virtual bool CanDeoptimize() const { return false; }
1085 1211
1212 virtual void PrintTo(BufferFormatter* f) const;
1213 virtual void PrintToVisualizer(BufferFormatter* f) const;
1214
1086 private: 1215 private:
1087 const intptr_t deopt_id_;
1088 const intptr_t token_pos_; 1216 const intptr_t token_pos_;
1089 1217
1090 DISALLOW_COPY_AND_ASSIGN(ReturnInstr); 1218 DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
1091 }; 1219 };
1092 1220
1093 1221
1094 class ThrowInstr : public TemplateInstruction<0> { 1222 class ThrowInstr : public TemplateInstruction<0> {
1095 public: 1223 public:
1096 explicit ThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { } 1224 explicit ThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { }
1097 1225
1098 DECLARE_INSTRUCTION(Throw) 1226 DECLARE_INSTRUCTION(Throw)
1099 1227
1100 virtual intptr_t ArgumentCount() const { return 1; } 1228 virtual intptr_t ArgumentCount() const { return 1; }
1101 1229
1102 intptr_t token_pos() const { return token_pos_; } 1230 intptr_t token_pos() const { return token_pos_; }
1103 1231
1104 virtual LocationSummary* MakeLocationSummary() const; 1232 virtual bool CanDeoptimize() const { return false; }
1105 1233
1106 virtual void EmitNativeCode(FlowGraphCompiler* compiler); 1234 virtual void PrintTo(BufferFormatter* f) const;
1107 1235 virtual void PrintToVisualizer(BufferFormatter* f) const;
1108 virtual bool CanDeoptimize() const { return false; }
1109 1236
1110 private: 1237 private:
1111 const intptr_t token_pos_; 1238 const intptr_t token_pos_;
1112 1239
1113 DISALLOW_COPY_AND_ASSIGN(ThrowInstr); 1240 DISALLOW_COPY_AND_ASSIGN(ThrowInstr);
1114 }; 1241 };
1115 1242
1116 1243
1117 class ReThrowInstr : public TemplateInstruction<0> { 1244 class ReThrowInstr : public TemplateInstruction<0> {
1118 public: 1245 public:
1119 explicit ReThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { } 1246 explicit ReThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { }
1120 1247
1121 DECLARE_INSTRUCTION(ReThrow) 1248 DECLARE_INSTRUCTION(ReThrow)
1122 1249
1123 virtual intptr_t ArgumentCount() const { return 2; } 1250 virtual intptr_t ArgumentCount() const { return 2; }
1124 1251
1125 intptr_t token_pos() const { return token_pos_; } 1252 intptr_t token_pos() const { return token_pos_; }
1126 1253
1127 virtual LocationSummary* MakeLocationSummary() const; 1254 virtual bool CanDeoptimize() const { return false; }
1128 1255
1129 virtual void EmitNativeCode(FlowGraphCompiler* compiler); 1256 virtual void PrintTo(BufferFormatter* f) const;
1130 1257 virtual void PrintToVisualizer(BufferFormatter* f) const;
1131 virtual bool CanDeoptimize() const { return false; }
1132 1258
1133 private: 1259 private:
1134 const intptr_t token_pos_; 1260 const intptr_t token_pos_;
1135 1261
1136 DISALLOW_COPY_AND_ASSIGN(ReThrowInstr); 1262 DISALLOW_COPY_AND_ASSIGN(ReThrowInstr);
1137 }; 1263 };
1138 1264
1139 1265
1140 class GotoInstr : public TemplateInstruction<0> { 1266 class GotoInstr : public TemplateInstruction<0> {
1141 public: 1267 public:
1142 explicit GotoInstr(JoinEntryInstr* entry) 1268 explicit GotoInstr(JoinEntryInstr* entry)
1143 : successor_(entry), 1269 : successor_(entry),
1144 parallel_move_(NULL) { } 1270 parallel_move_(NULL) { }
1145 1271
1146 DECLARE_INSTRUCTION(Goto) 1272 DECLARE_INSTRUCTION(Goto)
1147 1273
1148 virtual intptr_t ArgumentCount() const { return 0; } 1274 virtual intptr_t ArgumentCount() const { return 0; }
1149 1275
1150 JoinEntryInstr* successor() const { return successor_; } 1276 JoinEntryInstr* successor() const { return successor_; }
1151 void set_successor(JoinEntryInstr* successor) { successor_ = successor; } 1277 void set_successor(JoinEntryInstr* successor) { successor_ = successor; }
1152 virtual intptr_t SuccessorCount() const; 1278 virtual intptr_t SuccessorCount() const;
1153 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; 1279 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
1154 1280
1155 virtual LocationSummary* MakeLocationSummary() const;
1156
1157 virtual void EmitNativeCode(FlowGraphCompiler* compiler);
1158
1159 virtual bool CanDeoptimize() const { return false; } 1281 virtual bool CanDeoptimize() const { return false; }
1160 1282
1161 ParallelMoveInstr* parallel_move() const { 1283 ParallelMoveInstr* parallel_move() const {
1162 return parallel_move_; 1284 return parallel_move_;
1163 } 1285 }
1164 1286
1165 bool HasParallelMove() const { 1287 bool HasParallelMove() const {
1166 return parallel_move_ != NULL; 1288 return parallel_move_ != NULL;
1167 } 1289 }
1168 1290
1169 ParallelMoveInstr* GetParallelMove() { 1291 ParallelMoveInstr* GetParallelMove() {
1170 if (parallel_move_ == NULL) { 1292 if (parallel_move_ == NULL) {
1171 parallel_move_ = new ParallelMoveInstr(); 1293 parallel_move_ = new ParallelMoveInstr();
1172 } 1294 }
1173 return parallel_move_; 1295 return parallel_move_;
1174 } 1296 }
1175 1297
1298 virtual void PrintTo(BufferFormatter* f) const;
1299 virtual void PrintToVisualizer(BufferFormatter* f) const;
1300
1176 private: 1301 private:
1177 JoinEntryInstr* successor_; 1302 JoinEntryInstr* successor_;
1178 1303
1179 // Parallel move that will be used by linear scan register allocator to 1304 // Parallel move that will be used by linear scan register allocator to
1180 // connect live ranges at the end of the block and resolve phis. 1305 // connect live ranges at the end of the block and resolve phis.
1181 ParallelMoveInstr* parallel_move_; 1306 ParallelMoveInstr* parallel_move_;
1182 }; 1307 };
1183 1308
1184 1309
1185 class ControlInstruction : public Instruction { 1310 class ControlInstruction : public Instruction {
(...skipping 27 matching lines...) Expand all
1213 private: 1338 private:
1214 TargetEntryInstr* true_successor_; 1339 TargetEntryInstr* true_successor_;
1215 TargetEntryInstr* false_successor_; 1340 TargetEntryInstr* false_successor_;
1216 1341
1217 DISALLOW_COPY_AND_ASSIGN(ControlInstruction); 1342 DISALLOW_COPY_AND_ASSIGN(ControlInstruction);
1218 }; 1343 };
1219 1344
1220 1345
1221 class BranchInstr : public ControlInstruction { 1346 class BranchInstr : public ControlInstruction {
1222 public: 1347 public:
1223 explicit BranchInstr(ComparisonComp* computation) 1348 explicit BranchInstr(ComparisonInstr* comparison)
1224 : computation_(computation), locs_(NULL) { } 1349 : comparison_(comparison) { }
1225 1350
1226 DECLARE_INSTRUCTION(Branch) 1351 DECLARE_INSTRUCTION(Branch)
1227 1352
1228 virtual intptr_t ArgumentCount() const; 1353 virtual intptr_t ArgumentCount() const;
1229 intptr_t InputCount() const; 1354 intptr_t InputCount() const;
1230 Value* InputAt(intptr_t i) const; 1355 Value* InputAt(intptr_t i) const;
1231 void SetInputAt(intptr_t i, Value* value); 1356 void SetInputAt(intptr_t i, Value* value);
1232 virtual bool CanDeoptimize() const; 1357 virtual bool CanDeoptimize() const;
1233 1358
1234 ComparisonComp* computation() const { return computation_; } 1359 ComparisonInstr* comparison() const { return comparison_; }
1235 void set_computation(ComparisonComp* value) { computation_ = value; } 1360 void set_comparison(ComparisonInstr* value) { comparison_ = value; }
1236
1237 virtual void EmitNativeCode(FlowGraphCompiler* compiler);
1238 1361
1239 virtual LocationSummary* locs(); 1362 virtual LocationSummary* locs();
1240 virtual intptr_t DeoptimizationTarget() const; 1363 virtual intptr_t DeoptimizationTarget() const;
1241 virtual Representation RequiredInputRepresentation(intptr_t i) const; 1364 virtual Representation RequiredInputRepresentation(intptr_t i) const;
1242 1365
1366 // Replace the comparison with another, leaving the branch intact.
1367 void ReplaceWith(ComparisonInstr* other,
1368 ForwardInstructionIterator* ignored) {
1369 comparison_ = other;
1370 }
1371
1372 virtual void PrintTo(BufferFormatter* f) const;
1373 virtual void PrintToVisualizer(BufferFormatter* f) const;
1374
1243 private: 1375 private:
1244 ComparisonComp* computation_; 1376 ComparisonInstr* comparison_;
1245 LocationSummary* locs_;
1246 1377
1247 DISALLOW_COPY_AND_ASSIGN(BranchInstr); 1378 DISALLOW_COPY_AND_ASSIGN(BranchInstr);
1248 }; 1379 };
1249 1380
1250 1381
1251 #undef DECLARE_INSTRUCTION 1382 template<intptr_t N>
1383 class TemplateDefinition : public Definition {
1384 public:
1385 TemplateDefinition<N>() : locs_(NULL) { }
1252 1386
1253 1387 virtual intptr_t InputCount() const { return N; }
1254 // M is a two argument macro. It is applied to each concrete instruction's 1388 virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
1255 // (including the values) typename and classname. 1389 virtual void SetInputAt(intptr_t i, Value* value) {
1256 #define FOR_EACH_COMPUTATION(M) \ 1390 ASSERT(value != NULL);
1257 M(AssertAssignable, AssertAssignableComp) \ 1391 inputs_[i] = value;
1258 M(AssertBoolean, AssertBooleanComp) \
1259 M(ArgumentDefinitionTest, ArgumentDefinitionTestComp) \
1260 M(CurrentContext, CurrentContextComp) \
1261 M(StoreContext, StoreContextComp) \
1262 M(ClosureCall, ClosureCallComp) \
1263 M(InstanceCall, InstanceCallComp) \
1264 M(PolymorphicInstanceCall, PolymorphicInstanceCallComp) \
1265 M(StaticCall, StaticCallComp) \
1266 M(LoadLocal, LoadLocalComp) \
1267 M(StoreLocal, StoreLocalComp) \
1268 M(StrictCompare, StrictCompareComp) \
1269 M(EqualityCompare, EqualityCompareComp) \
1270 M(RelationalOp, RelationalOpComp) \
1271 M(NativeCall, NativeCallComp) \
1272 M(LoadIndexed, LoadIndexedComp) \
1273 M(StoreIndexed, StoreIndexedComp) \
1274 M(LoadInstanceField, LoadInstanceFieldComp) \
1275 M(StoreInstanceField, StoreInstanceFieldComp) \
1276 M(LoadStaticField, LoadStaticFieldComp) \
1277 M(StoreStaticField, StoreStaticFieldComp) \
1278 M(BooleanNegate, BooleanNegateComp) \
1279 M(InstanceOf, InstanceOfComp) \
1280 M(CreateArray, CreateArrayComp) \
1281 M(CreateClosure, CreateClosureComp) \
1282 M(AllocateObject, AllocateObjectComp) \
1283 M(AllocateObjectWithBoundsCheck, AllocateObjectWithBoundsCheckComp) \
1284 M(LoadVMField, LoadVMFieldComp) \
1285 M(StoreVMField, StoreVMFieldComp) \
1286 M(InstantiateTypeArguments, InstantiateTypeArgumentsComp) \
1287 M(ExtractConstructorTypeArguments, ExtractConstructorTypeArgumentsComp) \
1288 M(ExtractConstructorInstantiator, ExtractConstructorInstantiatorComp) \
1289 M(AllocateContext, AllocateContextComp) \
1290 M(ChainContext, ChainContextComp) \
1291 M(CloneContext, CloneContextComp) \
1292 M(CatchEntry, CatchEntryComp) \
1293 M(BinarySmiOp, BinarySmiOpComp) \
1294 M(BinaryMintOp, BinaryMintOpComp) \
1295 M(UnarySmiOp, UnarySmiOpComp) \
1296 M(NumberNegate, NumberNegateComp) \
1297 M(CheckStackOverflow, CheckStackOverflowComp) \
1298 M(DoubleToDouble, DoubleToDoubleComp) \
1299 M(SmiToDouble, SmiToDoubleComp) \
1300 M(CheckClass, CheckClassComp) \
1301 M(CheckSmi, CheckSmiComp) \
1302 M(Constant, ConstantComp) \
1303 M(CheckEitherNonSmi, CheckEitherNonSmiComp) \
1304 M(UnboxedDoubleBinaryOp, UnboxedDoubleBinaryOpComp) \
1305 M(UnboxDouble, UnboxDoubleComp) \
1306 M(BoxDouble, BoxDoubleComp) \
1307 M(CheckArrayBound, CheckArrayBoundComp)
1308
1309
1310 #define FORWARD_DECLARATION(ShortName, ClassName) class ClassName;
1311 FOR_EACH_COMPUTATION(FORWARD_DECLARATION)
1312 #undef FORWARD_DECLARATION
1313
1314
1315 class Computation : public ZoneAllocated {
1316 public:
1317 Computation()
1318 : deopt_id_(Isolate::Current()->GetNextDeoptId()), locs_(NULL) { }
1319
1320 // Unique id used for deoptimization.
1321 virtual intptr_t deopt_id() const {
1322 ASSERT(CanDeoptimize());
1323 return deopt_id_;
1324 } 1392 }
1325 1393
1326 // Visiting support. 1394 // Returns a structure describing the location constraints required
1327 virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr) = 0; 1395 // to emit native code for this definition.
1328
1329 virtual intptr_t InputCount() const = 0;
1330 virtual Value* InputAt(intptr_t i) const = 0;
1331 virtual void SetInputAt(intptr_t i, Value* value) = 0;
1332
1333 // Call computations override this function and return the
1334 // number of pushed arguments.
1335 virtual intptr_t ArgumentCount() const = 0;
1336
1337 // Returns true, if this computation can deoptimize.
1338 virtual bool CanDeoptimize() const = 0;
1339
1340 // Returns a replacement for the instruction that wraps this computation.
1341 // Returns NULL if instr can be eliminated.
1342 // By default returns instr (input parameter) which means no change.
1343 virtual Definition* TryReplace(BindInstr* instr) const;
1344
1345 // Compares two computations. Returns true, if:
1346 // 1. They are of the same kind.
1347 // 2. All input operands match.
1348 // 3. All other attributes match.
1349 bool Equals(Computation* other) const;
1350
1351 // Returns a hash code for use with hash maps.
1352 virtual intptr_t Hashcode() const;
1353
1354 // Compare attributes of an computation (except input operands and kind).
1355 // All computations that participate in CSE have to override this function.
1356 virtual bool AttributesEqual(Computation* other) const {
1357 UNREACHABLE();
1358 return false;
1359 }
1360
1361 // Returns true if the instruction may have side effects.
1362 // TODO(fschneider): Make this abstract and implement for all computations
1363 // instead of returning the safe default (true).
1364 virtual bool HasSideEffect() const { return true; }
1365
1366 // Compile time type of the computation, which typically depends on the
1367 // compile time types (and possibly propagated types) of its inputs.
1368 virtual RawAbstractType* CompileType() const = 0;
1369 virtual intptr_t ResultCid() const = 0;
1370
1371 // Mutate assigned_vars to add the local variable index for all
1372 // frame-allocated locals assigned to by the computation.
1373 virtual void RecordAssignedVars(BitVector* assigned_vars,
1374 intptr_t fixed_parameter_count);
1375
1376 virtual const char* DebugName() const = 0;
1377
1378 // Printing support. These functions are sometimes overridden for custom
1379 // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)".
1380 virtual void PrintTo(BufferFormatter* f) const;
1381 virtual void PrintOperandsTo(BufferFormatter* f) const;
1382
1383 // Returns structure describing location constraints required
1384 // to emit native code for this computation.
1385 LocationSummary* locs() { 1396 LocationSummary* locs() {
1386 if (locs_ == NULL) { 1397 if (locs_ == NULL) {
1387 locs_ = MakeLocationSummary(); 1398 locs_ = MakeLocationSummary();
1388 } 1399 }
1389 return locs_; 1400 return locs_;
1390 } 1401 }
1391 1402
1392 virtual ComparisonComp* AsComparison() { return NULL; }
1393
1394 // Create a location summary for this computation.
1395 // TODO(fschneider): Temporarily returns NULL for instructions
1396 // that are not yet converted to the location based code generation.
1397 virtual LocationSummary* MakeLocationSummary() const = 0;
1398
1399 // TODO(fschneider): Make EmitNativeCode and locs const.
1400 virtual void EmitNativeCode(FlowGraphCompiler* compiler) = 0;
1401
1402 virtual void EmitBranchCode(FlowGraphCompiler* compiler,
1403 BranchInstr* branch) {
1404 UNREACHABLE();
1405 }
1406
1407 static LocationSummary* MakeCallSummary();
1408
1409 // Declare an enum value used to define kind-test predicates.
1410 enum ComputationKind {
1411 #define DECLARE_COMPUTATION_KIND(ShortName, ClassName) k##ShortName,
1412
1413 FOR_EACH_COMPUTATION(DECLARE_COMPUTATION_KIND)
1414
1415 #undef DECLARE_COMPUTATION_KIND
1416 };
1417
1418 virtual ComputationKind computation_kind() const = 0;
1419
1420 // Returns representation expected for the input operand at the given index.
1421 virtual Representation RequiredInputRepresentation(intptr_t idx) const {
1422 return kTagged;
1423 }
1424
1425 // Representation of the value produced by this computation.
1426 virtual Representation representation() const {
1427 return kTagged;
1428 }
1429
1430 // Returns deoptimization id that corresponds to the deoptimization target
1431 // that input operands conversions inserted for this instruction can jump
1432 // to. Can return kNoDeoptId.
1433 virtual intptr_t DeoptimizationTarget() const {
1434 UNREACHABLE();
1435 return Isolate::kNoDeoptId;
1436 }
1437
1438 // Declare predicate for each computation.
1439 #define DECLARE_PREDICATE(ShortName, ClassName) \
1440 inline bool Is##ShortName() const; \
1441 inline const ClassName* As##ShortName() const; \
1442 inline ClassName* As##ShortName();
1443 FOR_EACH_COMPUTATION(DECLARE_PREDICATE)
1444 #undef DECLARE_PREDICATE
1445
1446 protected: 1403 protected:
1447 // Fetch deopt id without checking if this computation can deoptimize. 1404 EmbeddedArray<Value*, N> inputs_;
1448 intptr_t GetDeoptId() const {
1449 return deopt_id_;
1450 }
1451 1405
1452 private: 1406 private:
1453 friend class BranchInstr; 1407 friend class BranchInstr;
1454 1408
1455 intptr_t deopt_id_;
1456 LocationSummary* locs_; 1409 LocationSummary* locs_;
1457
1458 DISALLOW_COPY_AND_ASSIGN(Computation);
1459 }; 1410 };
1460 1411
1461 1412
1462 // Inlined functions from class BindInstr that forward to their computation. 1413 class ConstantInstr : public TemplateDefinition<0> {
1463 inline intptr_t BindInstr::ArgumentCount() const { 1414 public:
1464 return computation()->ArgumentCount(); 1415 explicit ConstantInstr(const Object& value) : value_(value) { }
1465 }
1466 1416
1467 1417 DECLARE_INSTRUCTION(Constant)
1468 inline intptr_t BindInstr::InputCount() const { 1418 virtual RawAbstractType* CompileType() const;
1469 return computation()->InputCount();
1470 }
1471
1472
1473 inline Value* BindInstr::InputAt(intptr_t i) const {
1474 return computation()->InputAt(i);
1475 }
1476
1477
1478 inline void BindInstr::SetInputAt(intptr_t i, Value* value) {
1479 computation()->SetInputAt(i, value);
1480 }
1481
1482 inline bool BindInstr::CanDeoptimize() const {
1483 return computation()->CanDeoptimize();
1484 }
1485
1486
1487 inline intptr_t BindInstr::Hashcode() const {
1488 return computation()->Hashcode();
1489 }
1490
1491
1492 inline bool BindInstr::Equals(BindInstr* other) const {
1493 return computation()->Equals(other->computation());
1494 }
1495
1496
1497 inline LocationSummary* BindInstr::locs() {
1498 return computation()->locs();
1499 }
1500
1501
1502 inline Representation BindInstr::RequiredInputRepresentation(intptr_t i) const {
1503 return computation()->RequiredInputRepresentation(i);
1504 }
1505
1506
1507 inline Representation BindInstr::representation() const {
1508 return computation()->representation();
1509 }
1510
1511
1512 inline intptr_t BindInstr::DeoptimizationTarget() const {
1513 return computation()->DeoptimizationTarget();
1514 }
1515
1516
1517 template<intptr_t N>
1518 class TemplateComputation : public Computation {
1519 public:
1520 virtual intptr_t InputCount() const { return N; }
1521 virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
1522 virtual void SetInputAt(intptr_t i, Value* value) {
1523 ASSERT(value != NULL);
1524 inputs_[i] = value;
1525 }
1526
1527 protected:
1528 EmbeddedArray<Value*, N> inputs_;
1529 };
1530
1531
1532 // Functions defined in all concrete computation classes.
1533 #define DECLARE_COMPUTATION(ShortName) \
1534 virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr); \
1535 virtual ComputationKind computation_kind() const { \
1536 return Computation::k##ShortName; \
1537 } \
1538 virtual intptr_t ArgumentCount() const { return 0; } \
1539 virtual const char* DebugName() const { return #ShortName; } \
1540 virtual RawAbstractType* CompileType() const; \
1541 virtual LocationSummary* MakeLocationSummary() const; \
1542 virtual void EmitNativeCode(FlowGraphCompiler* compiler);
1543
1544
1545 // Function defined in all call computation classes.
1546 #define DECLARE_CALL_COMPUTATION(ShortName) \
1547 virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr); \
1548 virtual ComputationKind computation_kind() const { \
1549 return Computation::k##ShortName; \
1550 } \
1551 virtual const char* DebugName() const { return #ShortName; } \
1552 virtual RawAbstractType* CompileType() const; \
1553 virtual LocationSummary* MakeLocationSummary() const; \
1554 virtual void EmitNativeCode(FlowGraphCompiler* compiler);
1555
1556
1557 class ConstantComp : public TemplateComputation<0> {
1558 public:
1559 explicit ConstantComp(const Object& value) : value_(value) { }
1560
1561 DECLARE_COMPUTATION(Constant)
1562 1419
1563 const Object& value() const { return value_; } 1420 const Object& value() const { return value_; }
1564 1421
1565 virtual void PrintOperandsTo(BufferFormatter* f) const; 1422 virtual void PrintOperandsTo(BufferFormatter* f) const;
1566 1423
1567 virtual bool CanDeoptimize() const { return false; } 1424 virtual bool CanDeoptimize() const { return false; }
1568 1425
1569 virtual intptr_t ResultCid() const; 1426 virtual intptr_t ResultCid() const;
1570 1427
1571 virtual bool AttributesEqual(Computation* other) const; 1428 virtual bool AttributesEqual(Definition* other) const;
1572 1429
1573 private: 1430 private:
1574 const Object& value_; 1431 const Object& value_;
1575 1432
1576 DISALLOW_COPY_AND_ASSIGN(ConstantComp); 1433 DISALLOW_COPY_AND_ASSIGN(ConstantInstr);
1577 }; 1434 };
1578 1435
1579 1436
1580 class AssertAssignableComp : public TemplateComputation<3> { 1437 class AssertAssignableInstr : public TemplateDefinition<3> {
1581 public: 1438 public:
1582 AssertAssignableComp(intptr_t token_pos, 1439 AssertAssignableInstr(intptr_t token_pos,
1583 Value* value, 1440 Value* value,
1584 Value* instantiator, 1441 Value* instantiator,
1585 Value* instantiator_type_arguments, 1442 Value* instantiator_type_arguments,
1586 const AbstractType& dst_type, 1443 const AbstractType& dst_type,
1587 const String& dst_name) 1444 const String& dst_name)
1588 : token_pos_(token_pos), 1445 : token_pos_(token_pos),
1589 dst_type_(dst_type), 1446 dst_type_(dst_type),
1590 dst_name_(dst_name), 1447 dst_name_(dst_name),
1591 is_eliminated_(false) { 1448 is_eliminated_(false) {
1592 ASSERT(value != NULL); 1449 ASSERT(value != NULL);
1593 ASSERT(instantiator != NULL); 1450 ASSERT(instantiator != NULL);
1594 ASSERT(instantiator_type_arguments != NULL); 1451 ASSERT(instantiator_type_arguments != NULL);
1595 ASSERT(!dst_type.IsNull()); 1452 ASSERT(!dst_type.IsNull());
1596 ASSERT(!dst_name.IsNull()); 1453 ASSERT(!dst_name.IsNull());
1597 inputs_[0] = value; 1454 inputs_[0] = value;
1598 inputs_[1] = instantiator; 1455 inputs_[1] = instantiator;
1599 inputs_[2] = instantiator_type_arguments; 1456 inputs_[2] = instantiator_type_arguments;
1600 } 1457 }
1601 1458
1602 DECLARE_COMPUTATION(AssertAssignable) 1459 DECLARE_INSTRUCTION(AssertAssignable)
1460 virtual RawAbstractType* CompileType() const;
1603 1461
1604 Value* value() const { return inputs_[0]; } 1462 Value* value() const { return inputs_[0]; }
1605 Value* instantiator() const { return inputs_[1]; } 1463 Value* instantiator() const { return inputs_[1]; }
1606 Value* instantiator_type_arguments() const { return inputs_[2]; } 1464 Value* instantiator_type_arguments() const { return inputs_[2]; }
1607 1465
1608 intptr_t token_pos() const { return token_pos_; } 1466 intptr_t token_pos() const { return token_pos_; }
1609 const AbstractType& dst_type() const { return dst_type_; } 1467 const AbstractType& dst_type() const { return dst_type_; }
1610 const String& dst_name() const { return dst_name_; } 1468 const String& dst_name() const { return dst_name_; }
1611 1469
1612 bool is_eliminated() const { 1470 bool is_eliminated() const {
1613 return is_eliminated_; 1471 return is_eliminated_;
1614 } 1472 }
1615 void eliminate() { 1473 void eliminate() {
1616 ASSERT(!is_eliminated_); 1474 ASSERT(!is_eliminated_);
1617 is_eliminated_ = true; 1475 is_eliminated_ = true;
1618 } 1476 }
1619 1477
1620 virtual void PrintOperandsTo(BufferFormatter* f) const; 1478 virtual void PrintOperandsTo(BufferFormatter* f) const;
1621 1479
1622 virtual bool CanDeoptimize() const { return false; } 1480 virtual bool CanDeoptimize() const { return false; }
1623 virtual intptr_t ResultCid() const { return kDynamicCid; } 1481 virtual intptr_t ResultCid() const { return kDynamicCid; }
1624 1482
1625 private: 1483 private:
1626 const intptr_t token_pos_; 1484 const intptr_t token_pos_;
1627 const AbstractType& dst_type_; 1485 const AbstractType& dst_type_;
1628 const String& dst_name_; 1486 const String& dst_name_;
1629 bool is_eliminated_; 1487 bool is_eliminated_;
1630 1488
1631 DISALLOW_COPY_AND_ASSIGN(AssertAssignableComp); 1489 DISALLOW_COPY_AND_ASSIGN(AssertAssignableInstr);
1632 }; 1490 };
1633 1491
1634 1492
1635 class AssertBooleanComp : public TemplateComputation<1> { 1493 class AssertBooleanInstr : public TemplateDefinition<1> {
1636 public: 1494 public:
1637 AssertBooleanComp(intptr_t token_pos, 1495 AssertBooleanInstr(intptr_t token_pos, Value* value)
1638 Value* value)
1639 : token_pos_(token_pos), 1496 : token_pos_(token_pos),
1640 is_eliminated_(false) { 1497 is_eliminated_(false) {
1641 ASSERT(value != NULL); 1498 ASSERT(value != NULL);
1642 inputs_[0] = value; 1499 inputs_[0] = value;
1643 } 1500 }
1644 1501
1645 DECLARE_COMPUTATION(AssertBoolean) 1502 DECLARE_INSTRUCTION(AssertBoolean)
1503 virtual RawAbstractType* CompileType() const;
1646 1504
1647 intptr_t token_pos() const { return token_pos_; } 1505 intptr_t token_pos() const { return token_pos_; }
1648 Value* value() const { return inputs_[0]; } 1506 Value* value() const { return inputs_[0]; }
1649 1507
1650 bool is_eliminated() const { 1508 bool is_eliminated() const {
1651 return is_eliminated_; 1509 return is_eliminated_;
1652 } 1510 }
1653 void eliminate() { 1511 void eliminate() {
1654 ASSERT(!is_eliminated_); 1512 ASSERT(!is_eliminated_);
1655 is_eliminated_ = true; 1513 is_eliminated_ = true;
1656 } 1514 }
1657 1515
1658 virtual void PrintOperandsTo(BufferFormatter* f) const; 1516 virtual void PrintOperandsTo(BufferFormatter* f) const;
1659 1517
1660 virtual bool CanDeoptimize() const { return false; } 1518 virtual bool CanDeoptimize() const { return false; }
1661 virtual intptr_t ResultCid() const { return kBoolCid; } 1519 virtual intptr_t ResultCid() const { return kBoolCid; }
1662 1520
1663 private: 1521 private:
1664 const intptr_t token_pos_; 1522 const intptr_t token_pos_;
1665 bool is_eliminated_; 1523 bool is_eliminated_;
1666 1524
1667 DISALLOW_COPY_AND_ASSIGN(AssertBooleanComp); 1525 DISALLOW_COPY_AND_ASSIGN(AssertBooleanInstr);
1668 }; 1526 };
1669 1527
1670 1528
1671 class ArgumentDefinitionTestComp : public TemplateComputation<1> { 1529 class ArgumentDefinitionTestInstr : public TemplateDefinition<1> {
1672 public: 1530 public:
1673 ArgumentDefinitionTestComp(ArgumentDefinitionTestNode* node, 1531 ArgumentDefinitionTestInstr(ArgumentDefinitionTestNode* node,
1674 Value* saved_arguments_descriptor) 1532 Value* saved_arguments_descriptor)
1675 : ast_node_(*node) { 1533 : ast_node_(*node) {
1676 ASSERT(saved_arguments_descriptor != NULL); 1534 ASSERT(saved_arguments_descriptor != NULL);
1677 inputs_[0] = saved_arguments_descriptor; 1535 inputs_[0] = saved_arguments_descriptor;
1678 } 1536 }
1679 1537
1680 DECLARE_COMPUTATION(ArgumentDefinitionTest) 1538 DECLARE_INSTRUCTION(ArgumentDefinitionTest)
1539 virtual RawAbstractType* CompileType() const;
1681 1540
1682 intptr_t token_pos() const { return ast_node_.token_pos(); } 1541 intptr_t token_pos() const { return ast_node_.token_pos(); }
1683 intptr_t formal_parameter_index() const { 1542 intptr_t formal_parameter_index() const {
1684 return ast_node_.formal_parameter_index(); 1543 return ast_node_.formal_parameter_index();
1685 } 1544 }
1686 const String& formal_parameter_name() const { 1545 const String& formal_parameter_name() const {
1687 return ast_node_.formal_parameter_name(); 1546 return ast_node_.formal_parameter_name();
1688 } 1547 }
1689 Value* saved_arguments_descriptor() const { return inputs_[0]; } 1548 Value* saved_arguments_descriptor() const { return inputs_[0]; }
1690 1549
1691 virtual void PrintOperandsTo(BufferFormatter* f) const; 1550 virtual void PrintOperandsTo(BufferFormatter* f) const;
1692 1551
1693 virtual bool CanDeoptimize() const { return false; } 1552 virtual bool CanDeoptimize() const { return false; }
1694 virtual intptr_t ResultCid() const { return kBoolCid; } 1553 virtual intptr_t ResultCid() const { return kBoolCid; }
1695 1554
1696 private: 1555 private:
1697 const ArgumentDefinitionTestNode& ast_node_; 1556 const ArgumentDefinitionTestNode& ast_node_;
1698 1557
1699 DISALLOW_COPY_AND_ASSIGN(ArgumentDefinitionTestComp); 1558 DISALLOW_COPY_AND_ASSIGN(ArgumentDefinitionTestInstr);
1700 }; 1559 };
1701 1560
1702 1561
1703 // Denotes the current context, normally held in a register. This is 1562 // Denotes the current context, normally held in a register. This is
1704 // a computation, not a value, because it's mutable. 1563 // a computation, not a value, because it's mutable.
1705 class CurrentContextComp : public TemplateComputation<0> { 1564 class CurrentContextInstr : public TemplateDefinition<0> {
1706 public: 1565 public:
1707 CurrentContextComp() { } 1566 CurrentContextInstr() { }
1708 1567
1709 DECLARE_COMPUTATION(CurrentContext) 1568 DECLARE_INSTRUCTION(CurrentContext)
1569 virtual RawAbstractType* CompileType() const;
1710 1570
1711 virtual bool CanDeoptimize() const { return false; } 1571 virtual bool CanDeoptimize() const { return false; }
1712 virtual intptr_t ResultCid() const { return kDynamicCid; } 1572 virtual intptr_t ResultCid() const { return kDynamicCid; }
1713 1573
1714 private: 1574 private:
1715 DISALLOW_COPY_AND_ASSIGN(CurrentContextComp); 1575 DISALLOW_COPY_AND_ASSIGN(CurrentContextInstr);
1716 }; 1576 };
1717 1577
1718 1578
1719 class StoreContextComp : public TemplateComputation<1> { 1579 class StoreContextInstr : public TemplateDefinition<1> {
1720 public: 1580 public:
1721 explicit StoreContextComp(Value* value) { 1581 explicit StoreContextInstr(Value* value) {
1722 ASSERT(value != NULL); 1582 ASSERT(value != NULL);
1723 inputs_[0] = value; 1583 inputs_[0] = value;
1724 } 1584 }
1725 1585
1726 DECLARE_COMPUTATION(StoreContext); 1586 DECLARE_INSTRUCTION(StoreContext);
1587 virtual RawAbstractType* CompileType() const;
1727 1588
1728 Value* value() const { return inputs_[0]; } 1589 Value* value() const { return inputs_[0]; }
1729 1590
1730 virtual bool CanDeoptimize() const { return false; } 1591 virtual bool CanDeoptimize() const { return false; }
1731 virtual intptr_t ResultCid() const { return kIllegalCid; } 1592 virtual intptr_t ResultCid() const { return kIllegalCid; }
1732 1593
1733 private: 1594 private:
1734 DISALLOW_COPY_AND_ASSIGN(StoreContextComp); 1595 DISALLOW_COPY_AND_ASSIGN(StoreContextInstr);
1735 }; 1596 };
1736 1597
1737 1598
1738 class ClosureCallComp : public TemplateComputation<0> { 1599 class ClosureCallInstr : public TemplateDefinition<0> {
1739 public: 1600 public:
1740 ClosureCallComp(ClosureCallNode* node, 1601 ClosureCallInstr(ClosureCallNode* node,
1741 ZoneGrowableArray<PushArgumentInstr*>* arguments) 1602 ZoneGrowableArray<PushArgumentInstr*>* arguments)
1742 : ast_node_(*node), 1603 : ast_node_(*node),
1743 arguments_(arguments) { } 1604 arguments_(arguments) { }
1744 1605
1745 DECLARE_CALL_COMPUTATION(ClosureCall) 1606 DECLARE_INSTRUCTION(ClosureCall)
1607 virtual RawAbstractType* CompileType() const;
1746 1608
1747 const Array& argument_names() const { return ast_node_.arguments()->names(); } 1609 const Array& argument_names() const { return ast_node_.arguments()->names(); }
1748 intptr_t token_pos() const { return ast_node_.token_pos(); } 1610 intptr_t token_pos() const { return ast_node_.token_pos(); }
1749 1611
1750 virtual intptr_t ArgumentCount() const { return arguments_->length(); } 1612 virtual intptr_t ArgumentCount() const { return arguments_->length(); }
1751 PushArgumentInstr* ArgumentAt(intptr_t index) const { 1613 PushArgumentInstr* ArgumentAt(intptr_t index) const {
1752 return (*arguments_)[index]; 1614 return (*arguments_)[index];
1753 } 1615 }
1754 1616
1755 virtual void PrintOperandsTo(BufferFormatter* f) const; 1617 virtual void PrintOperandsTo(BufferFormatter* f) const;
1756 1618
1757 virtual bool CanDeoptimize() const { return true; } 1619 virtual bool CanDeoptimize() const { return true; }
1758 virtual intptr_t ResultCid() const { return kDynamicCid; } 1620 virtual intptr_t ResultCid() const { return kDynamicCid; }
1759 1621
1760 private: 1622 private:
1761 const ClosureCallNode& ast_node_; 1623 const ClosureCallNode& ast_node_;
1762 ZoneGrowableArray<PushArgumentInstr*>* arguments_; 1624 ZoneGrowableArray<PushArgumentInstr*>* arguments_;
1763 1625
1764 DISALLOW_COPY_AND_ASSIGN(ClosureCallComp); 1626 DISALLOW_COPY_AND_ASSIGN(ClosureCallInstr);
1765 }; 1627 };
1766 1628
1767 1629
1768 class InstanceCallComp : public TemplateComputation<0> { 1630 class InstanceCallInstr : public TemplateDefinition<0> {
1769 public: 1631 public:
1770 InstanceCallComp(intptr_t token_pos, 1632 InstanceCallInstr(intptr_t token_pos,
1771 const String& function_name, 1633 const String& function_name,
1772 Token::Kind token_kind, 1634 Token::Kind token_kind,
1773 ZoneGrowableArray<PushArgumentInstr*>* arguments, 1635 ZoneGrowableArray<PushArgumentInstr*>* arguments,
1774 const Array& argument_names, 1636 const Array& argument_names,
1775 intptr_t checked_argument_count) 1637 intptr_t checked_argument_count)
1776 : ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())), 1638 : ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
1777 token_pos_(token_pos), 1639 token_pos_(token_pos),
1778 function_name_(function_name), 1640 function_name_(function_name),
1779 token_kind_(token_kind), 1641 token_kind_(token_kind),
1780 arguments_(arguments), 1642 arguments_(arguments),
1781 argument_names_(argument_names), 1643 argument_names_(argument_names),
1782 checked_argument_count_(checked_argument_count) { 1644 checked_argument_count_(checked_argument_count) {
1783 ASSERT(function_name.IsZoneHandle()); 1645 ASSERT(function_name.IsZoneHandle());
1784 ASSERT(!arguments->is_empty()); 1646 ASSERT(!arguments->is_empty());
1785 ASSERT(argument_names.IsZoneHandle()); 1647 ASSERT(argument_names.IsZoneHandle());
1786 ASSERT(Token::IsBinaryToken(token_kind) || 1648 ASSERT(Token::IsBinaryToken(token_kind) ||
1787 Token::IsUnaryToken(token_kind) || 1649 Token::IsUnaryToken(token_kind) ||
1788 Token::IsIndexOperator(token_kind) || 1650 Token::IsIndexOperator(token_kind) ||
1789 token_kind == Token::kGET || 1651 token_kind == Token::kGET ||
1790 token_kind == Token::kSET || 1652 token_kind == Token::kSET ||
1791 token_kind == Token::kILLEGAL); 1653 token_kind == Token::kILLEGAL);
1792 } 1654 }
1793 1655
1794 DECLARE_CALL_COMPUTATION(InstanceCall) 1656 DECLARE_INSTRUCTION(InstanceCall)
1657 virtual RawAbstractType* CompileType() const;
1795 1658
1796 const ICData* ic_data() const { return ic_data_; } 1659 const ICData* ic_data() const { return ic_data_; }
1797 bool HasICData() const { 1660 bool HasICData() const {
1798 return (ic_data() != NULL) && !ic_data()->IsNull(); 1661 return (ic_data() != NULL) && !ic_data()->IsNull();
1799 } 1662 }
1800 1663
1801 intptr_t token_pos() const { return token_pos_; } 1664 intptr_t token_pos() const { return token_pos_; }
1802 const String& function_name() const { return function_name_; } 1665 const String& function_name() const { return function_name_; }
1803 Token::Kind token_kind() const { return token_kind_; } 1666 Token::Kind token_kind() const { return token_kind_; }
1804 virtual intptr_t ArgumentCount() const { return arguments_->length(); } 1667 virtual intptr_t ArgumentCount() const { return arguments_->length(); }
(...skipping 10 matching lines...) Expand all
1815 1678
1816 private: 1679 private:
1817 const ICData* ic_data_; 1680 const ICData* ic_data_;
1818 const intptr_t token_pos_; 1681 const intptr_t token_pos_;
1819 const String& function_name_; 1682 const String& function_name_;
1820 const Token::Kind token_kind_; // Binary op, unary op, kGET or kILLEGAL. 1683 const Token::Kind token_kind_; // Binary op, unary op, kGET or kILLEGAL.
1821 ZoneGrowableArray<PushArgumentInstr*>* const arguments_; 1684 ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
1822 const Array& argument_names_; 1685 const Array& argument_names_;
1823 const intptr_t checked_argument_count_; 1686 const intptr_t checked_argument_count_;
1824 1687
1825 DISALLOW_COPY_AND_ASSIGN(InstanceCallComp); 1688 DISALLOW_COPY_AND_ASSIGN(InstanceCallInstr);
1826 }; 1689 };
1827 1690
1828 1691
1829 class PolymorphicInstanceCallComp : public TemplateComputation<0> { 1692 class PolymorphicInstanceCallInstr : public TemplateDefinition<0> {
1830 public: 1693 public:
1831 PolymorphicInstanceCallComp(InstanceCallComp* comp, 1694 PolymorphicInstanceCallInstr(InstanceCallInstr* instance_call,
1832 const ICData& ic_data, 1695 const ICData& ic_data,
1833 bool with_checks) 1696 bool with_checks)
1834 : instance_call_(comp), ic_data_(ic_data), with_checks_(with_checks) { 1697 : instance_call_(instance_call),
1698 ic_data_(ic_data),
1699 with_checks_(with_checks) {
1835 ASSERT(instance_call_ != NULL); 1700 ASSERT(instance_call_ != NULL);
1836 } 1701 }
1837 1702
1838 InstanceCallComp* instance_call() const { return instance_call_; } 1703 InstanceCallInstr* instance_call() const { return instance_call_; }
1839 bool with_checks() const { return with_checks_; } 1704 bool with_checks() const { return with_checks_; }
1840 1705
1841 void PrintTo(BufferFormatter* f) const;
1842
1843 virtual intptr_t ArgumentCount() const { 1706 virtual intptr_t ArgumentCount() const {
1844 return instance_call()->ArgumentCount(); 1707 return instance_call()->ArgumentCount();
1845 } 1708 }
1846 1709
1847 DECLARE_CALL_COMPUTATION(PolymorphicInstanceCall) 1710 DECLARE_INSTRUCTION(PolymorphicInstanceCall)
1711 virtual RawAbstractType* CompileType() const;
1848 1712
1849 const ICData& ic_data() const { return ic_data_; } 1713 const ICData& ic_data() const { return ic_data_; }
1850 1714
1851 virtual bool CanDeoptimize() const { return true; } 1715 virtual bool CanDeoptimize() const { return true; }
1852 virtual intptr_t ResultCid() const { return kDynamicCid; } 1716 virtual intptr_t ResultCid() const { return kDynamicCid; }
1853 1717
1718 virtual void PrintTo(BufferFormatter* f) const;
1719
1854 private: 1720 private:
1855 InstanceCallComp* instance_call_; 1721 InstanceCallInstr* instance_call_;
1856 const ICData& ic_data_; 1722 const ICData& ic_data_;
1857 const bool with_checks_; 1723 const bool with_checks_;
1858 1724
1859 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallComp); 1725 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallInstr);
1860 }; 1726 };
1861 1727
1862 1728
1863 class ComparisonComp : public TemplateComputation<2> { 1729 class ComparisonInstr : public TemplateDefinition<2> {
1864 public: 1730 public:
1865 ComparisonComp(Token::Kind kind, Value* left, Value* right) : kind_(kind) { 1731 ComparisonInstr(Token::Kind kind, Value* left, Value* right) : kind_(kind) {
1866 ASSERT(left != NULL); 1732 ASSERT(left != NULL);
1867 ASSERT(right != NULL); 1733 ASSERT(right != NULL);
1868 inputs_[0] = left; 1734 inputs_[0] = left;
1869 inputs_[1] = right; 1735 inputs_[1] = right;
1870 } 1736 }
1871 1737
1872 Value* left() const { return inputs_[0]; } 1738 Value* left() const { return inputs_[0]; }
1873 Value* right() const { return inputs_[1]; } 1739 Value* right() const { return inputs_[1]; }
1874 1740
1875 virtual ComparisonComp* AsComparison() { return this; } 1741 virtual ComparisonInstr* AsComparison() { return this; }
1876 1742
1877 Token::Kind kind() const { return kind_; } 1743 Token::Kind kind() const { return kind_; }
1878 1744
1745 virtual void EmitBranchCode(FlowGraphCompiler* compiler,
1746 BranchInstr* branch) = 0;
1747
1879 private: 1748 private:
1880 Token::Kind kind_; 1749 Token::Kind kind_;
1881 }; 1750 };
1882 1751
1883 1752
1884 // Inlined functions from class BranchInstr that forward to their comparison. 1753 // Inlined functions from class BranchInstr that forward to their comparison.
1885 inline intptr_t BranchInstr::ArgumentCount() const { 1754 inline intptr_t BranchInstr::ArgumentCount() const {
1886 return computation()->ArgumentCount(); 1755 return comparison()->ArgumentCount();
1887 } 1756 }
1888 1757
1889 1758
1890 inline intptr_t BranchInstr::InputCount() const { 1759 inline intptr_t BranchInstr::InputCount() const {
1891 return computation()->InputCount(); 1760 return comparison()->InputCount();
1892 } 1761 }
1893 1762
1894 1763
1895 inline Value* BranchInstr::InputAt(intptr_t i) const { 1764 inline Value* BranchInstr::InputAt(intptr_t i) const {
1896 return computation()->InputAt(i); 1765 return comparison()->InputAt(i);
1897 } 1766 }
1898 1767
1899 1768
1900 inline void BranchInstr::SetInputAt(intptr_t i, Value* value) { 1769 inline void BranchInstr::SetInputAt(intptr_t i, Value* value) {
1901 computation()->SetInputAt(i, value); 1770 comparison()->SetInputAt(i, value);
1902 } 1771 }
1903 1772
1904 1773
1905 inline bool BranchInstr::CanDeoptimize() const { 1774 inline bool BranchInstr::CanDeoptimize() const {
1906 return computation()->CanDeoptimize(); 1775 return comparison()->CanDeoptimize();
1907 } 1776 }
1908 1777
1909 1778
1910 inline LocationSummary* BranchInstr::locs() { 1779 inline LocationSummary* BranchInstr::locs() {
1911 if (computation_->locs_ == NULL) { 1780 if (comparison()->locs_ == NULL) {
1912 LocationSummary* summary = computation_->MakeLocationSummary(); 1781 LocationSummary* summary = comparison()->MakeLocationSummary();
1913 // Branches don't produce a result. 1782 // Branches don't produce a result.
1914 summary->set_out(Location::NoLocation()); 1783 summary->set_out(Location::NoLocation());
1915 computation_->locs_ = summary; 1784 comparison()->locs_ = summary;
1916 } 1785 }
1917 return computation_->locs_; 1786 return comparison()->locs_;
1918 } 1787 }
1919 1788
1920 1789
1921 inline intptr_t BranchInstr::DeoptimizationTarget() const { 1790 inline intptr_t BranchInstr::DeoptimizationTarget() const {
1922 return computation_->DeoptimizationTarget(); 1791 return comparison()->DeoptimizationTarget();
1923 } 1792 }
1924 1793
1925 1794
1926 inline Representation BranchInstr::RequiredInputRepresentation( 1795 inline Representation BranchInstr::RequiredInputRepresentation(
1927 intptr_t i) const { 1796 intptr_t i) const {
1928 return computation()->RequiredInputRepresentation(i); 1797 return comparison()->RequiredInputRepresentation(i);
1929 } 1798 }
1930 1799
1931 1800
1932 class StrictCompareComp : public ComparisonComp { 1801 class StrictCompareInstr : public ComparisonInstr {
1933 public: 1802 public:
1934 StrictCompareComp(Token::Kind kind, Value* left, Value* right) 1803 StrictCompareInstr(Token::Kind kind, Value* left, Value* right)
1935 : ComparisonComp(kind, left, right) { 1804 : ComparisonInstr(kind, left, right) {
1936 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); 1805 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
1937 } 1806 }
1938 1807
1939 DECLARE_COMPUTATION(StrictCompare) 1808 DECLARE_INSTRUCTION(StrictCompare)
1809 virtual RawAbstractType* CompileType() const;
1940 1810
1941 virtual void PrintOperandsTo(BufferFormatter* f) const; 1811 virtual void PrintOperandsTo(BufferFormatter* f) const;
1942 1812
1943 virtual bool CanDeoptimize() const { return false; } 1813 virtual bool CanDeoptimize() const { return false; }
1944 1814
1945 virtual Definition* TryReplace(BindInstr* instr) const; 1815 virtual Definition* Canonicalize();
1946 1816
1947 virtual intptr_t ResultCid() const { return kBoolCid; } 1817 virtual intptr_t ResultCid() const { return kBoolCid; }
1948 1818
1949 virtual void EmitBranchCode(FlowGraphCompiler* compiler, 1819 virtual void EmitBranchCode(FlowGraphCompiler* compiler,
1950 BranchInstr* branch); 1820 BranchInstr* branch);
1951 1821
1952 private: 1822 private:
1953 DISALLOW_COPY_AND_ASSIGN(StrictCompareComp); 1823 DISALLOW_COPY_AND_ASSIGN(StrictCompareInstr);
1954 }; 1824 };
1955 1825
1956 1826
1957 class EqualityCompareComp : public ComparisonComp { 1827 class EqualityCompareInstr : public ComparisonInstr {
1958 public: 1828 public:
1959 EqualityCompareComp(intptr_t token_pos, 1829 EqualityCompareInstr(intptr_t token_pos,
1960 Token::Kind kind, 1830 Token::Kind kind,
1961 Value* left, 1831 Value* left,
1962 Value* right) 1832 Value* right)
1963 : ComparisonComp(kind, left, right), 1833 : ComparisonInstr(kind, left, right),
1964 ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())), 1834 ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
1965 token_pos_(token_pos), 1835 token_pos_(token_pos),
1966 receiver_class_id_(kIllegalCid) { 1836 receiver_class_id_(kIllegalCid) {
1967 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 1837 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
1968 } 1838 }
1969 1839
1970 DECLARE_COMPUTATION(EqualityCompare) 1840 DECLARE_INSTRUCTION(EqualityCompare)
1841 virtual RawAbstractType* CompileType() const;
1971 1842
1972 const ICData* ic_data() const { return ic_data_; } 1843 const ICData* ic_data() const { return ic_data_; }
1973 bool HasICData() const { 1844 bool HasICData() const {
1974 return (ic_data() != NULL) && !ic_data()->IsNull(); 1845 return (ic_data() != NULL) && !ic_data()->IsNull();
1975 } 1846 }
1976 1847
1977 intptr_t token_pos() const { return token_pos_; } 1848 intptr_t token_pos() const { return token_pos_; }
1978 1849
1979 // Receiver class id is computed from collected ICData. 1850 // Receiver class id is computed from collected ICData.
1980 void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; } 1851 void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; }
(...skipping 18 matching lines...) Expand all
1999 virtual Representation RequiredInputRepresentation(intptr_t idx) const { 1870 virtual Representation RequiredInputRepresentation(intptr_t idx) const {
2000 ASSERT((idx == 0) || (idx == 1)); 1871 ASSERT((idx == 0) || (idx == 1));
2001 return (receiver_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged; 1872 return (receiver_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged;
2002 } 1873 }
2003 1874
2004 private: 1875 private:
2005 const ICData* ic_data_; 1876 const ICData* ic_data_;
2006 const intptr_t token_pos_; 1877 const intptr_t token_pos_;
2007 intptr_t receiver_class_id_; // Set by optimizer. 1878 intptr_t receiver_class_id_; // Set by optimizer.
2008 1879
2009 DISALLOW_COPY_AND_ASSIGN(EqualityCompareComp); 1880 DISALLOW_COPY_AND_ASSIGN(EqualityCompareInstr);
2010 }; 1881 };
2011 1882
2012 1883
2013 class RelationalOpComp : public ComparisonComp { 1884 class RelationalOpInstr : public ComparisonInstr {
2014 public: 1885 public:
2015 RelationalOpComp(intptr_t token_pos, 1886 RelationalOpInstr(intptr_t token_pos,
2016 Token::Kind kind, 1887 Token::Kind kind,
2017 Value* left, 1888 Value* left,
2018 Value* right) 1889 Value* right)
2019 : ComparisonComp(kind, left, right), 1890 : ComparisonInstr(kind, left, right),
2020 ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())), 1891 ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
2021 token_pos_(token_pos), 1892 token_pos_(token_pos),
2022 operands_class_id_(kIllegalCid) { 1893 operands_class_id_(kIllegalCid) {
2023 ASSERT(Token::IsRelationalOperator(kind)); 1894 ASSERT(Token::IsRelationalOperator(kind));
2024 } 1895 }
2025 1896
2026 DECLARE_COMPUTATION(RelationalOp) 1897 DECLARE_INSTRUCTION(RelationalOp)
1898 virtual RawAbstractType* CompileType() const;
2027 1899
2028 const ICData* ic_data() const { return ic_data_; } 1900 const ICData* ic_data() const { return ic_data_; }
2029 bool HasICData() const { 1901 bool HasICData() const {
2030 return (ic_data() != NULL) && !ic_data()->IsNull(); 1902 return (ic_data() != NULL) && !ic_data()->IsNull();
2031 } 1903 }
2032 1904
2033 intptr_t token_pos() const { return token_pos_; } 1905 intptr_t token_pos() const { return token_pos_; }
2034 1906
2035 // TODO(srdjan): instead of class-id pass an enum that can differentiate 1907 // TODO(srdjan): instead of class-id pass an enum that can differentiate
2036 // between boxed and unboxed doubles and integers. 1908 // between boxed and unboxed doubles and integers.
(...skipping 23 matching lines...) Expand all
2060 virtual Representation RequiredInputRepresentation(intptr_t idx) const { 1932 virtual Representation RequiredInputRepresentation(intptr_t idx) const {
2061 ASSERT((idx == 0) || (idx == 1)); 1933 ASSERT((idx == 0) || (idx == 1));
2062 return (operands_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged; 1934 return (operands_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged;
2063 } 1935 }
2064 1936
2065 private: 1937 private:
2066 const ICData* ic_data_; 1938 const ICData* ic_data_;
2067 const intptr_t token_pos_; 1939 const intptr_t token_pos_;
2068 intptr_t operands_class_id_; // class id of both operands. 1940 intptr_t operands_class_id_; // class id of both operands.
2069 1941
2070 DISALLOW_COPY_AND_ASSIGN(RelationalOpComp); 1942 DISALLOW_COPY_AND_ASSIGN(RelationalOpInstr);
2071 }; 1943 };
2072 1944
2073 1945
2074 class StaticCallComp : public TemplateComputation<0> { 1946 class StaticCallInstr : public TemplateDefinition<0> {
2075 public: 1947 public:
2076 StaticCallComp(intptr_t token_pos, 1948 StaticCallInstr(intptr_t token_pos,
2077 const Function& function, 1949 const Function& function,
2078 const Array& argument_names, 1950 const Array& argument_names,
2079 ZoneGrowableArray<PushArgumentInstr*>* arguments) 1951 ZoneGrowableArray<PushArgumentInstr*>* arguments)
2080 : token_pos_(token_pos), 1952 : token_pos_(token_pos),
2081 function_(function), 1953 function_(function),
2082 argument_names_(argument_names), 1954 argument_names_(argument_names),
2083 arguments_(arguments), 1955 arguments_(arguments),
2084 recognized_(MethodRecognizer::kUnknown) { 1956 recognized_(MethodRecognizer::kUnknown) {
2085 ASSERT(function.IsZoneHandle()); 1957 ASSERT(function.IsZoneHandle());
2086 ASSERT(argument_names.IsZoneHandle()); 1958 ASSERT(argument_names.IsZoneHandle());
2087 } 1959 }
2088 1960
2089 DECLARE_CALL_COMPUTATION(StaticCall) 1961 DECLARE_INSTRUCTION(StaticCall)
1962 virtual RawAbstractType* CompileType() const;
2090 1963
2091 // Accessors forwarded to the AST node. 1964 // Accessors forwarded to the AST node.
2092 const Function& function() const { return function_; } 1965 const Function& function() const { return function_; }
2093 const Array& argument_names() const { return argument_names_; } 1966 const Array& argument_names() const { return argument_names_; }
2094 intptr_t token_pos() const { return token_pos_; } 1967 intptr_t token_pos() const { return token_pos_; }
2095 1968
2096 virtual intptr_t ArgumentCount() const { return arguments_->length(); } 1969 virtual intptr_t ArgumentCount() const { return arguments_->length(); }
2097 PushArgumentInstr* ArgumentAt(intptr_t index) const { 1970 PushArgumentInstr* ArgumentAt(intptr_t index) const {
2098 return (*arguments_)[index]; 1971 return (*arguments_)[index];
2099 } 1972 }
2100 1973
2101 MethodRecognizer::Kind recognized() const { return recognized_; } 1974 MethodRecognizer::Kind recognized() const { return recognized_; }
2102 void set_recognized(MethodRecognizer::Kind kind) { recognized_ = kind; } 1975 void set_recognized(MethodRecognizer::Kind kind) { recognized_ = kind; }
2103 1976
2104 virtual void PrintOperandsTo(BufferFormatter* f) const; 1977 virtual void PrintOperandsTo(BufferFormatter* f) const;
2105 1978
2106 virtual bool CanDeoptimize() const { return true; } 1979 virtual bool CanDeoptimize() const { return true; }
2107 virtual intptr_t ResultCid() const { return kDynamicCid; } 1980 virtual intptr_t ResultCid() const { return kDynamicCid; }
2108 1981
2109 private: 1982 private:
2110 const intptr_t token_pos_; 1983 const intptr_t token_pos_;
2111 const Function& function_; 1984 const Function& function_;
2112 const Array& argument_names_; 1985 const Array& argument_names_;
2113 ZoneGrowableArray<PushArgumentInstr*>* arguments_; 1986 ZoneGrowableArray<PushArgumentInstr*>* arguments_;
2114 MethodRecognizer::Kind recognized_; 1987 MethodRecognizer::Kind recognized_;
2115 1988
2116 DISALLOW_COPY_AND_ASSIGN(StaticCallComp); 1989 DISALLOW_COPY_AND_ASSIGN(StaticCallInstr);
2117 }; 1990 };
2118 1991
2119 1992
2120 class LoadLocalComp : public TemplateComputation<0> { 1993 class LoadLocalInstr : public TemplateDefinition<0> {
2121 public: 1994 public:
2122 LoadLocalComp(const LocalVariable& local, intptr_t context_level) 1995 LoadLocalInstr(const LocalVariable& local, intptr_t context_level)
2123 : local_(local), 1996 : local_(local),
2124 context_level_(context_level) { } 1997 context_level_(context_level) { }
2125 1998
2126 DECLARE_COMPUTATION(LoadLocal) 1999 DECLARE_INSTRUCTION(LoadLocal)
2000 virtual RawAbstractType* CompileType() const;
2127 2001
2128 const LocalVariable& local() const { return local_; } 2002 const LocalVariable& local() const { return local_; }
2129 intptr_t context_level() const { return context_level_; } 2003 intptr_t context_level() const { return context_level_; }
2130 2004
2131 virtual void PrintOperandsTo(BufferFormatter* f) const; 2005 virtual void PrintOperandsTo(BufferFormatter* f) const;
2132 2006
2133 virtual bool CanDeoptimize() const { return false; } 2007 virtual bool CanDeoptimize() const { return false; }
2134 virtual intptr_t ResultCid() const { return kDynamicCid; } 2008 virtual intptr_t ResultCid() const { return kDynamicCid; }
2135 2009
2136 private: 2010 private:
2137 const LocalVariable& local_; 2011 const LocalVariable& local_;
2138 const intptr_t context_level_; 2012 const intptr_t context_level_;
2139 2013
2140 DISALLOW_COPY_AND_ASSIGN(LoadLocalComp); 2014 DISALLOW_COPY_AND_ASSIGN(LoadLocalInstr);
2141 }; 2015 };
2142 2016
2143 2017
2144 class StoreLocalComp : public TemplateComputation<1> { 2018 class StoreLocalInstr : public TemplateDefinition<1> {
2145 public: 2019 public:
2146 StoreLocalComp(const LocalVariable& local, 2020 StoreLocalInstr(const LocalVariable& local,
2147 Value* value, 2021 Value* value,
2148 intptr_t context_level) 2022 intptr_t context_level)
2149 : local_(local), 2023 : local_(local),
2150 context_level_(context_level) { 2024 context_level_(context_level) {
2151 ASSERT(value != NULL); 2025 ASSERT(value != NULL);
2152 inputs_[0] = value; 2026 inputs_[0] = value;
2153 } 2027 }
2154 2028
2155 DECLARE_COMPUTATION(StoreLocal) 2029 DECLARE_INSTRUCTION(StoreLocal)
2030 virtual RawAbstractType* CompileType() const;
2156 2031
2157 const LocalVariable& local() const { return local_; } 2032 const LocalVariable& local() const { return local_; }
2158 Value* value() const { return inputs_[0]; } 2033 Value* value() const { return inputs_[0]; }
2159 intptr_t context_level() const { return context_level_; } 2034 intptr_t context_level() const { return context_level_; }
2160 2035
2161 virtual void RecordAssignedVars(BitVector* assigned_vars, 2036 virtual void RecordAssignedVars(BitVector* assigned_vars,
2162 intptr_t fixed_parameter_count); 2037 intptr_t fixed_parameter_count);
2163 2038
2164 virtual void PrintOperandsTo(BufferFormatter* f) const; 2039 virtual void PrintOperandsTo(BufferFormatter* f) const;
2165 2040
2166 virtual bool CanDeoptimize() const { return false; } 2041 virtual bool CanDeoptimize() const { return false; }
2167 virtual intptr_t ResultCid() const { return kDynamicCid; } 2042 virtual intptr_t ResultCid() const { return kDynamicCid; }
2168 2043
2169 private: 2044 private:
2170 const LocalVariable& local_; 2045 const LocalVariable& local_;
2171 const intptr_t context_level_; 2046 const intptr_t context_level_;
2172 2047
2173 DISALLOW_COPY_AND_ASSIGN(StoreLocalComp); 2048 DISALLOW_COPY_AND_ASSIGN(StoreLocalInstr);
2174 }; 2049 };
2175 2050
2176 2051
2177 class NativeCallComp : public TemplateComputation<0> { 2052 class NativeCallInstr : public TemplateDefinition<0> {
2178 public: 2053 public:
2179 explicit NativeCallComp(NativeBodyNode* node) 2054 explicit NativeCallInstr(NativeBodyNode* node)
2180 : ast_node_(*node) {} 2055 : ast_node_(*node) {}
2181 2056
2182 DECLARE_COMPUTATION(NativeCall) 2057 DECLARE_INSTRUCTION(NativeCall)
2058 virtual RawAbstractType* CompileType() const;
2183 2059
2184 intptr_t token_pos() const { return ast_node_.token_pos(); } 2060 intptr_t token_pos() const { return ast_node_.token_pos(); }
2185 2061
2186 const String& native_name() const { 2062 const String& native_name() const {
2187 return ast_node_.native_c_function_name(); 2063 return ast_node_.native_c_function_name();
2188 } 2064 }
2189 2065
2190 NativeFunction native_c_function() const { 2066 NativeFunction native_c_function() const {
2191 return ast_node_.native_c_function(); 2067 return ast_node_.native_c_function();
2192 } 2068 }
2193 2069
2194 intptr_t argument_count() const { return ast_node_.argument_count(); } 2070 intptr_t argument_count() const { return ast_node_.argument_count(); }
2195 2071
2196 bool has_optional_parameters() const { 2072 bool has_optional_parameters() const {
2197 return ast_node_.has_optional_parameters(); 2073 return ast_node_.has_optional_parameters();
2198 } 2074 }
2199 2075
2200 bool is_native_instance_closure() const { 2076 bool is_native_instance_closure() const {
2201 return ast_node_.is_native_instance_closure(); 2077 return ast_node_.is_native_instance_closure();
2202 } 2078 }
2203 2079
2204 virtual void PrintOperandsTo(BufferFormatter* f) const; 2080 virtual void PrintOperandsTo(BufferFormatter* f) const;
2205 2081
2206 virtual bool CanDeoptimize() const { return false; } 2082 virtual bool CanDeoptimize() const { return false; }
2207 virtual intptr_t ResultCid() const { return kDynamicCid; } 2083 virtual intptr_t ResultCid() const { return kDynamicCid; }
2208 2084
2209 private: 2085 private:
2210 const NativeBodyNode& ast_node_; 2086 const NativeBodyNode& ast_node_;
2211 2087
2212 DISALLOW_COPY_AND_ASSIGN(NativeCallComp); 2088 DISALLOW_COPY_AND_ASSIGN(NativeCallInstr);
2213 }; 2089 };
2214 2090
2215 2091
2216 class LoadInstanceFieldComp : public TemplateComputation<1> { 2092 class LoadInstanceFieldInstr : public TemplateDefinition<1> {
2217 public: 2093 public:
2218 LoadInstanceFieldComp(const Field& field, Value* instance) : field_(field) { 2094 LoadInstanceFieldInstr(const Field& field, Value* instance) : field_(field) {
2219 ASSERT(instance != NULL); 2095 ASSERT(instance != NULL);
2220 inputs_[0] = instance; 2096 inputs_[0] = instance;
2221 } 2097 }
2222 2098
2223 DECLARE_COMPUTATION(LoadInstanceField) 2099 DECLARE_INSTRUCTION(LoadInstanceField)
2100 virtual RawAbstractType* CompileType() const;
2224 2101
2225 const Field& field() const { return field_; } 2102 const Field& field() const { return field_; }
2226 Value* instance() const { return inputs_[0]; } 2103 Value* instance() const { return inputs_[0]; }
2227 2104
2228 virtual void PrintOperandsTo(BufferFormatter* f) const; 2105 virtual void PrintOperandsTo(BufferFormatter* f) const;
2229 2106
2230 virtual bool CanDeoptimize() const { return false; } 2107 virtual bool CanDeoptimize() const { return false; }
2231 virtual intptr_t ResultCid() const { return kDynamicCid; } 2108 virtual intptr_t ResultCid() const { return kDynamicCid; }
2232 2109
2233 private: 2110 private:
2234 const Field& field_; 2111 const Field& field_;
2235 2112
2236 DISALLOW_COPY_AND_ASSIGN(LoadInstanceFieldComp); 2113 DISALLOW_COPY_AND_ASSIGN(LoadInstanceFieldInstr);
2237 }; 2114 };
2238 2115
2239 2116
2240 class StoreInstanceFieldComp : public TemplateComputation<2> { 2117 class StoreInstanceFieldInstr : public TemplateDefinition<2> {
2241 public: 2118 public:
2242 StoreInstanceFieldComp(const Field& field, 2119 StoreInstanceFieldInstr(const Field& field, Value* instance, Value* value)
2243 Value* instance,
2244 Value* value)
2245 : field_(field) { 2120 : field_(field) {
2246 ASSERT(instance != NULL); 2121 ASSERT(instance != NULL);
2247 ASSERT(value != NULL); 2122 ASSERT(value != NULL);
2248 inputs_[0] = instance; 2123 inputs_[0] = instance;
2249 inputs_[1] = value; 2124 inputs_[1] = value;
2250 } 2125 }
2251 2126
2252 DECLARE_COMPUTATION(StoreInstanceField) 2127 DECLARE_INSTRUCTION(StoreInstanceField)
2128 virtual RawAbstractType* CompileType() const;
2253 2129
2254 const Field& field() const { return field_; } 2130 const Field& field() const { return field_; }
2255 2131
2256 Value* instance() const { return inputs_[0]; } 2132 Value* instance() const { return inputs_[0]; }
2257 Value* value() const { return inputs_[1]; } 2133 Value* value() const { return inputs_[1]; }
2258 2134
2259 virtual void PrintOperandsTo(BufferFormatter* f) const; 2135 virtual void PrintOperandsTo(BufferFormatter* f) const;
2260 2136
2261 virtual bool CanDeoptimize() const { return false; } 2137 virtual bool CanDeoptimize() const { return false; }
2262 virtual intptr_t ResultCid() const { return kDynamicCid; } 2138 virtual intptr_t ResultCid() const { return kDynamicCid; }
2263 2139
2264 private: 2140 private:
2265 const Field& field_; 2141 const Field& field_;
2266 2142
2267 DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldComp); 2143 DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr);
2268 }; 2144 };
2269 2145
2270 2146
2271 class LoadStaticFieldComp : public TemplateComputation<0> { 2147 class LoadStaticFieldInstr : public TemplateDefinition<0> {
2272 public: 2148 public:
2273 explicit LoadStaticFieldComp(const Field& field) : field_(field) {} 2149 explicit LoadStaticFieldInstr(const Field& field) : field_(field) {}
2274 2150
2275 DECLARE_COMPUTATION(LoadStaticField); 2151 DECLARE_INSTRUCTION(LoadStaticField);
2152 virtual RawAbstractType* CompileType() const;
2276 2153
2277 const Field& field() const { return field_; } 2154 const Field& field() const { return field_; }
2278 2155
2279 virtual void PrintOperandsTo(BufferFormatter* f) const; 2156 virtual void PrintOperandsTo(BufferFormatter* f) const;
2280 2157
2281 virtual bool CanDeoptimize() const { return false; } 2158 virtual bool CanDeoptimize() const { return false; }
2282 virtual intptr_t ResultCid() const { return kDynamicCid; } 2159 virtual intptr_t ResultCid() const { return kDynamicCid; }
2283 2160
2284 private: 2161 private:
2285 const Field& field_; 2162 const Field& field_;
2286 2163
2287 DISALLOW_COPY_AND_ASSIGN(LoadStaticFieldComp); 2164 DISALLOW_COPY_AND_ASSIGN(LoadStaticFieldInstr);
2288 }; 2165 };
2289 2166
2290 2167
2291 class StoreStaticFieldComp : public TemplateComputation<1> { 2168 class StoreStaticFieldInstr : public TemplateDefinition<1> {
2292 public: 2169 public:
2293 StoreStaticFieldComp(const Field& field, Value* value) 2170 StoreStaticFieldInstr(const Field& field, Value* value)
2294 : field_(field) { 2171 : field_(field) {
2295 ASSERT(field.IsZoneHandle()); 2172 ASSERT(field.IsZoneHandle());
2296 ASSERT(value != NULL); 2173 ASSERT(value != NULL);
2297 inputs_[0] = value; 2174 inputs_[0] = value;
2298 } 2175 }
2299 2176
2300 DECLARE_COMPUTATION(StoreStaticField); 2177 DECLARE_INSTRUCTION(StoreStaticField);
2178 virtual RawAbstractType* CompileType() const;
2301 2179
2302 const Field& field() const { return field_; } 2180 const Field& field() const { return field_; }
2303 Value* value() const { return inputs_[0]; } 2181 Value* value() const { return inputs_[0]; }
2304 2182
2305 virtual void PrintOperandsTo(BufferFormatter* f) const; 2183 virtual void PrintOperandsTo(BufferFormatter* f) const;
2306 2184
2307 virtual bool CanDeoptimize() const { return false; } 2185 virtual bool CanDeoptimize() const { return false; }
2308 virtual intptr_t ResultCid() const { return kDynamicCid; } 2186 virtual intptr_t ResultCid() const { return kDynamicCid; }
2309 2187
2310 private: 2188 private:
2311 const Field& field_; 2189 const Field& field_;
2312 2190
2313 DISALLOW_COPY_AND_ASSIGN(StoreStaticFieldComp); 2191 DISALLOW_COPY_AND_ASSIGN(StoreStaticFieldInstr);
2314 }; 2192 };
2315 2193
2316 2194
2317 class LoadIndexedComp : public TemplateComputation<2> { 2195 class LoadIndexedInstr : public TemplateDefinition<2> {
2318 public: 2196 public:
2319 LoadIndexedComp(Value* array, 2197 LoadIndexedInstr(Value* array, Value* index, intptr_t receiver_type)
2320 Value* index,
2321 intptr_t receiver_type)
2322 : receiver_type_(receiver_type) { 2198 : receiver_type_(receiver_type) {
2323 ASSERT(array != NULL); 2199 ASSERT(array != NULL);
2324 ASSERT(index != NULL); 2200 ASSERT(index != NULL);
2325 inputs_[0] = array; 2201 inputs_[0] = array;
2326 inputs_[1] = index; 2202 inputs_[1] = index;
2327 } 2203 }
2328 2204
2329 DECLARE_COMPUTATION(LoadIndexed) 2205 DECLARE_INSTRUCTION(LoadIndexed)
2206 virtual RawAbstractType* CompileType() const;
2330 2207
2331 Value* array() const { return inputs_[0]; } 2208 Value* array() const { return inputs_[0]; }
2332 Value* index() const { return inputs_[1]; } 2209 Value* index() const { return inputs_[1]; }
2333 2210
2334 intptr_t receiver_type() const { return receiver_type_; } 2211 intptr_t receiver_type() const { return receiver_type_; }
2335 2212
2336 virtual bool CanDeoptimize() const { return false; } 2213 virtual bool CanDeoptimize() const { return false; }
2337 virtual intptr_t ResultCid() const { return kDynamicCid; } 2214 virtual intptr_t ResultCid() const { return kDynamicCid; }
2338 2215
2339 private: 2216 private:
2340 intptr_t receiver_type_; 2217 intptr_t receiver_type_;
2341 2218
2342 DISALLOW_COPY_AND_ASSIGN(LoadIndexedComp); 2219 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr);
2343 }; 2220 };
2344 2221
2345 2222
2346 class StoreIndexedComp : public TemplateComputation<3> { 2223 class StoreIndexedInstr : public TemplateDefinition<3> {
2347 public: 2224 public:
2348 StoreIndexedComp(Value* array, 2225 StoreIndexedInstr(Value* array,
2349 Value* index, 2226 Value* index,
2350 Value* value, 2227 Value* value,
2351 intptr_t receiver_type) 2228 intptr_t receiver_type)
2352 : receiver_type_(receiver_type) { 2229 : receiver_type_(receiver_type) {
2353 ASSERT(array != NULL); 2230 ASSERT(array != NULL);
2354 ASSERT(index != NULL); 2231 ASSERT(index != NULL);
2355 ASSERT(value != NULL); 2232 ASSERT(value != NULL);
2356 inputs_[0] = array; 2233 inputs_[0] = array;
2357 inputs_[1] = index; 2234 inputs_[1] = index;
2358 inputs_[2] = value; 2235 inputs_[2] = value;
2359 } 2236 }
2360 2237
2361 DECLARE_COMPUTATION(StoreIndexed) 2238 DECLARE_INSTRUCTION(StoreIndexed)
2239 virtual RawAbstractType* CompileType() const;
2362 2240
2363 Value* array() const { return inputs_[0]; } 2241 Value* array() const { return inputs_[0]; }
2364 Value* index() const { return inputs_[1]; } 2242 Value* index() const { return inputs_[1]; }
2365 Value* value() const { return inputs_[2]; } 2243 Value* value() const { return inputs_[2]; }
2366 2244
2367 intptr_t receiver_type() const { return receiver_type_; } 2245 intptr_t receiver_type() const { return receiver_type_; }
2368 2246
2369 virtual bool CanDeoptimize() const { return false; } 2247 virtual bool CanDeoptimize() const { return false; }
2370 virtual intptr_t ResultCid() const { return kDynamicCid; } 2248 virtual intptr_t ResultCid() const { return kDynamicCid; }
2371 2249
2372 private: 2250 private:
2373 intptr_t receiver_type_; 2251 intptr_t receiver_type_;
2374 2252
2375 DISALLOW_COPY_AND_ASSIGN(StoreIndexedComp); 2253 DISALLOW_COPY_AND_ASSIGN(StoreIndexedInstr);
2376 }; 2254 };
2377 2255
2378 2256
2379 // Note overrideable, built-in: value? false : true. 2257 // Note overrideable, built-in: value? false : true.
2380 class BooleanNegateComp : public TemplateComputation<1> { 2258 class BooleanNegateInstr : public TemplateDefinition<1> {
2381 public: 2259 public:
2382 explicit BooleanNegateComp(Value* value) { 2260 explicit BooleanNegateInstr(Value* value) {
2383 ASSERT(value != NULL); 2261 ASSERT(value != NULL);
2384 inputs_[0] = value; 2262 inputs_[0] = value;
2385 } 2263 }
2386 2264
2387 DECLARE_COMPUTATION(BooleanNegate) 2265 DECLARE_INSTRUCTION(BooleanNegate)
2266 virtual RawAbstractType* CompileType() const;
2388 2267
2389 Value* value() const { return inputs_[0]; } 2268 Value* value() const { return inputs_[0]; }
2390 2269
2391 virtual bool CanDeoptimize() const { return false; } 2270 virtual bool CanDeoptimize() const { return false; }
2392 virtual intptr_t ResultCid() const { return kBoolCid; } 2271 virtual intptr_t ResultCid() const { return kBoolCid; }
2393 2272
2394 private: 2273 private:
2395 DISALLOW_COPY_AND_ASSIGN(BooleanNegateComp); 2274 DISALLOW_COPY_AND_ASSIGN(BooleanNegateInstr);
2396 }; 2275 };
2397 2276
2398 2277
2399 class InstanceOfComp : public TemplateComputation<3> { 2278 class InstanceOfInstr : public TemplateDefinition<3> {
2400 public: 2279 public:
2401 InstanceOfComp(intptr_t token_pos, 2280 InstanceOfInstr(intptr_t token_pos,
2402 Value* value, 2281 Value* value,
2403 Value* instantiator, 2282 Value* instantiator,
2404 Value* instantiator_type_arguments, 2283 Value* instantiator_type_arguments,
2405 const AbstractType& type, 2284 const AbstractType& type,
2406 bool negate_result) 2285 bool negate_result)
2407 : token_pos_(token_pos), 2286 : token_pos_(token_pos),
2408 type_(type), 2287 type_(type),
2409 negate_result_(negate_result) { 2288 negate_result_(negate_result) {
2410 ASSERT(value != NULL); 2289 ASSERT(value != NULL);
2411 ASSERT(instantiator != NULL); 2290 ASSERT(instantiator != NULL);
2412 ASSERT(instantiator_type_arguments != NULL); 2291 ASSERT(instantiator_type_arguments != NULL);
2413 ASSERT(!type.IsNull()); 2292 ASSERT(!type.IsNull());
2414 inputs_[0] = value; 2293 inputs_[0] = value;
2415 inputs_[1] = instantiator; 2294 inputs_[1] = instantiator;
2416 inputs_[2] = instantiator_type_arguments; 2295 inputs_[2] = instantiator_type_arguments;
2417 } 2296 }
2418 2297
2419 DECLARE_COMPUTATION(InstanceOf) 2298 DECLARE_INSTRUCTION(InstanceOf)
2299 virtual RawAbstractType* CompileType() const;
2420 2300
2421 Value* value() const { return inputs_[0]; } 2301 Value* value() const { return inputs_[0]; }
2422 Value* instantiator() const { return inputs_[1]; } 2302 Value* instantiator() const { return inputs_[1]; }
2423 Value* instantiator_type_arguments() const { return inputs_[2]; } 2303 Value* instantiator_type_arguments() const { return inputs_[2]; }
2424 2304
2425 bool negate_result() const { return negate_result_; } 2305 bool negate_result() const { return negate_result_; }
2426 const AbstractType& type() const { return type_; } 2306 const AbstractType& type() const { return type_; }
2427 intptr_t token_pos() const { return token_pos_; } 2307 intptr_t token_pos() const { return token_pos_; }
2428 2308
2429 virtual void PrintOperandsTo(BufferFormatter* f) const; 2309 virtual void PrintOperandsTo(BufferFormatter* f) const;
2430 2310
2431 virtual bool CanDeoptimize() const { return false; } 2311 virtual bool CanDeoptimize() const { return false; }
2432 virtual intptr_t ResultCid() const { return kBoolCid; } 2312 virtual intptr_t ResultCid() const { return kBoolCid; }
2433 2313
2434 private: 2314 private:
2435 const intptr_t token_pos_; 2315 const intptr_t token_pos_;
2436 Value* value_; 2316 Value* value_;
2437 Value* instantiator_; 2317 Value* instantiator_;
2438 Value* type_arguments_; 2318 Value* type_arguments_;
2439 const AbstractType& type_; 2319 const AbstractType& type_;
2440 const bool negate_result_; 2320 const bool negate_result_;
2441 2321
2442 DISALLOW_COPY_AND_ASSIGN(InstanceOfComp); 2322 DISALLOW_COPY_AND_ASSIGN(InstanceOfInstr);
2443 }; 2323 };
2444 2324
2445 2325
2446 class AllocateObjectComp : public TemplateComputation<0> { 2326 class AllocateObjectInstr : public TemplateDefinition<0> {
2447 public: 2327 public:
2448 AllocateObjectComp(ConstructorCallNode* node, 2328 AllocateObjectInstr(ConstructorCallNode* node,
2449 ZoneGrowableArray<PushArgumentInstr*>* arguments) 2329 ZoneGrowableArray<PushArgumentInstr*>* arguments)
2450 : ast_node_(*node), arguments_(arguments) { 2330 : ast_node_(*node), arguments_(arguments) {
2451 // Either no arguments or one type-argument and one instantiator. 2331 // Either no arguments or one type-argument and one instantiator.
2452 ASSERT(arguments->is_empty() || (arguments->length() == 2)); 2332 ASSERT(arguments->is_empty() || (arguments->length() == 2));
2453 } 2333 }
2454 2334
2455 DECLARE_CALL_COMPUTATION(AllocateObject) 2335 DECLARE_INSTRUCTION(AllocateObject)
2336 virtual RawAbstractType* CompileType() const;
2456 2337
2457 virtual intptr_t ArgumentCount() const { return arguments_->length(); } 2338 virtual intptr_t ArgumentCount() const { return arguments_->length(); }
2458 PushArgumentInstr* ArgumentAt(intptr_t index) const { 2339 PushArgumentInstr* ArgumentAt(intptr_t index) const {
2459 return (*arguments_)[index]; 2340 return (*arguments_)[index];
2460 } 2341 }
2461 2342
2462 const Function& constructor() const { return ast_node_.constructor(); } 2343 const Function& constructor() const { return ast_node_.constructor(); }
2463 intptr_t token_pos() const { return ast_node_.token_pos(); } 2344 intptr_t token_pos() const { return ast_node_.token_pos(); }
2464 2345
2465 virtual void PrintOperandsTo(BufferFormatter* f) const; 2346 virtual void PrintOperandsTo(BufferFormatter* f) const;
2466 2347
2467 virtual bool CanDeoptimize() const { return false; } 2348 virtual bool CanDeoptimize() const { return false; }
2468 virtual intptr_t ResultCid() const { return kDynamicCid; } 2349 virtual intptr_t ResultCid() const { return kDynamicCid; }
2469 2350
2470 private: 2351 private:
2471 const ConstructorCallNode& ast_node_; 2352 const ConstructorCallNode& ast_node_;
2472 ZoneGrowableArray<PushArgumentInstr*>* const arguments_; 2353 ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
2473 2354
2474 DISALLOW_COPY_AND_ASSIGN(AllocateObjectComp); 2355 DISALLOW_COPY_AND_ASSIGN(AllocateObjectInstr);
2475 }; 2356 };
2476 2357
2477 2358
2478 class AllocateObjectWithBoundsCheckComp : public TemplateComputation<2> { 2359 class AllocateObjectWithBoundsCheckInstr : public TemplateDefinition<2> {
2479 public: 2360 public:
2480 AllocateObjectWithBoundsCheckComp(ConstructorCallNode* node, 2361 AllocateObjectWithBoundsCheckInstr(ConstructorCallNode* node,
2481 Value* type_arguments, 2362 Value* type_arguments,
2482 Value* instantiator) 2363 Value* instantiator)
2483 : ast_node_(*node) { 2364 : ast_node_(*node) {
2484 ASSERT(type_arguments != NULL); 2365 ASSERT(type_arguments != NULL);
2485 ASSERT(instantiator != NULL); 2366 ASSERT(instantiator != NULL);
2486 inputs_[0] = type_arguments; 2367 inputs_[0] = type_arguments;
2487 inputs_[1] = instantiator; 2368 inputs_[1] = instantiator;
2488 } 2369 }
2489 2370
2490 DECLARE_COMPUTATION(AllocateObjectWithBoundsCheck) 2371 DECLARE_INSTRUCTION(AllocateObjectWithBoundsCheck)
2372 virtual RawAbstractType* CompileType() const;
2491 2373
2492 const Function& constructor() const { return ast_node_.constructor(); } 2374 const Function& constructor() const { return ast_node_.constructor(); }
2493 intptr_t token_pos() const { return ast_node_.token_pos(); } 2375 intptr_t token_pos() const { return ast_node_.token_pos(); }
2494 2376
2495 virtual void PrintOperandsTo(BufferFormatter* f) const; 2377 virtual void PrintOperandsTo(BufferFormatter* f) const;
2496 2378
2497 virtual bool CanDeoptimize() const { return false; } 2379 virtual bool CanDeoptimize() const { return false; }
2498 virtual intptr_t ResultCid() const { return kDynamicCid; } 2380 virtual intptr_t ResultCid() const { return kDynamicCid; }
2499 2381
2500 private: 2382 private:
2501 const ConstructorCallNode& ast_node_; 2383 const ConstructorCallNode& ast_node_;
2502 2384
2503 DISALLOW_COPY_AND_ASSIGN(AllocateObjectWithBoundsCheckComp); 2385 DISALLOW_COPY_AND_ASSIGN(AllocateObjectWithBoundsCheckInstr);
2504 }; 2386 };
2505 2387
2506 2388
2507 class CreateArrayComp : public TemplateComputation<1> { 2389 class CreateArrayInstr : public TemplateDefinition<1> {
2508 public: 2390 public:
2509 CreateArrayComp(intptr_t token_pos, 2391 CreateArrayInstr(intptr_t token_pos,
2510 ZoneGrowableArray<PushArgumentInstr*>* arguments, 2392 ZoneGrowableArray<PushArgumentInstr*>* arguments,
2511 const AbstractType& type, 2393 const AbstractType& type,
2512 Value* element_type) 2394 Value* element_type)
2513 : token_pos_(token_pos), 2395 : token_pos_(token_pos),
2514 arguments_(arguments), 2396 arguments_(arguments),
2515 type_(type) { 2397 type_(type) {
2516 #if defined(DEBUG) 2398 #if defined(DEBUG)
2517 for (int i = 0; i < ArgumentCount(); ++i) { 2399 for (int i = 0; i < ArgumentCount(); ++i) {
2518 ASSERT(ArgumentAt(i) != NULL); 2400 ASSERT(ArgumentAt(i) != NULL);
2519 } 2401 }
2520 ASSERT(element_type != NULL); 2402 ASSERT(element_type != NULL);
2521 ASSERT(type_.IsZoneHandle()); 2403 ASSERT(type_.IsZoneHandle());
2522 ASSERT(!type_.IsNull()); 2404 ASSERT(!type_.IsNull());
2523 ASSERT(type_.IsFinalized()); 2405 ASSERT(type_.IsFinalized());
2524 #endif 2406 #endif
2525 inputs_[0] = element_type; 2407 inputs_[0] = element_type;
2526 } 2408 }
2527 2409
2528 DECLARE_CALL_COMPUTATION(CreateArray) 2410 DECLARE_INSTRUCTION(CreateArray)
2411 virtual RawAbstractType* CompileType() const;
2529 2412
2530 virtual intptr_t ArgumentCount() const { return arguments_->length(); } 2413 virtual intptr_t ArgumentCount() const { return arguments_->length(); }
2531 2414
2532 intptr_t token_pos() const { return token_pos_; } 2415 intptr_t token_pos() const { return token_pos_; }
2533 PushArgumentInstr* ArgumentAt(intptr_t i) const { return (*arguments_)[i]; } 2416 PushArgumentInstr* ArgumentAt(intptr_t i) const { return (*arguments_)[i]; }
2534 const AbstractType& type() const { return type_; } 2417 const AbstractType& type() const { return type_; }
2535 Value* element_type() const { return inputs_[0]; } 2418 Value* element_type() const { return inputs_[0]; }
2536 2419
2537 virtual void PrintOperandsTo(BufferFormatter* f) const; 2420 virtual void PrintOperandsTo(BufferFormatter* f) const;
2538 2421
2539 virtual bool CanDeoptimize() const { return false; } 2422 virtual bool CanDeoptimize() const { return false; }
2540 virtual intptr_t ResultCid() const { return kDynamicCid; } 2423 virtual intptr_t ResultCid() const { return kDynamicCid; }
2541 2424
2542 private: 2425 private:
2543 const intptr_t token_pos_; 2426 const intptr_t token_pos_;
2544 ZoneGrowableArray<PushArgumentInstr*>* const arguments_; 2427 ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
2545 const AbstractType& type_; 2428 const AbstractType& type_;
2546 2429
2547 DISALLOW_COPY_AND_ASSIGN(CreateArrayComp); 2430 DISALLOW_COPY_AND_ASSIGN(CreateArrayInstr);
2548 }; 2431 };
2549 2432
2550 2433
2551 class CreateClosureComp : public TemplateComputation<0> { 2434 class CreateClosureInstr : public TemplateDefinition<0> {
2552 public: 2435 public:
2553 CreateClosureComp(ClosureNode* node, 2436 CreateClosureInstr(ClosureNode* node,
2554 ZoneGrowableArray<PushArgumentInstr*>* arguments) 2437 ZoneGrowableArray<PushArgumentInstr*>* arguments)
2555 : ast_node_(*node), 2438 : ast_node_(*node),
2556 arguments_(arguments) { } 2439 arguments_(arguments) { }
2557 2440
2558 DECLARE_CALL_COMPUTATION(CreateClosure) 2441 DECLARE_INSTRUCTION(CreateClosure)
2442 virtual RawAbstractType* CompileType() const;
2559 2443
2560 intptr_t token_pos() const { return ast_node_.token_pos(); } 2444 intptr_t token_pos() const { return ast_node_.token_pos(); }
2561 const Function& function() const { return ast_node_.function(); } 2445 const Function& function() const { return ast_node_.function(); }
2562 2446
2563 virtual intptr_t ArgumentCount() const { return arguments_->length(); } 2447 virtual intptr_t ArgumentCount() const { return arguments_->length(); }
2564 PushArgumentInstr* ArgumentAt(intptr_t index) const { 2448 PushArgumentInstr* ArgumentAt(intptr_t index) const {
2565 return (*arguments_)[index]; 2449 return (*arguments_)[index];
2566 } 2450 }
2567 2451
2568 virtual void PrintOperandsTo(BufferFormatter* f) const; 2452 virtual void PrintOperandsTo(BufferFormatter* f) const;
2569 2453
2570 virtual bool CanDeoptimize() const { return false; } 2454 virtual bool CanDeoptimize() const { return false; }
2571 virtual intptr_t ResultCid() const { return kDynamicCid; } 2455 virtual intptr_t ResultCid() const { return kDynamicCid; }
2572 2456
2573 private: 2457 private:
2574 const ClosureNode& ast_node_; 2458 const ClosureNode& ast_node_;
2575 ZoneGrowableArray<PushArgumentInstr*>* arguments_; 2459 ZoneGrowableArray<PushArgumentInstr*>* arguments_;
2576 2460
2577 DISALLOW_COPY_AND_ASSIGN(CreateClosureComp); 2461 DISALLOW_COPY_AND_ASSIGN(CreateClosureInstr);
2578 }; 2462 };
2579 2463
2580 2464
2581 class LoadVMFieldComp : public TemplateComputation<1> { 2465 class LoadVMFieldInstr : public TemplateDefinition<1> {
2582 public: 2466 public:
2583 LoadVMFieldComp(Value* value, 2467 LoadVMFieldInstr(Value* value,
2584 intptr_t offset_in_bytes, 2468 intptr_t offset_in_bytes,
2585 const AbstractType& type) 2469 const AbstractType& type)
2586 : offset_in_bytes_(offset_in_bytes), 2470 : offset_in_bytes_(offset_in_bytes),
2587 type_(type), 2471 type_(type),
2588 result_cid_(kDynamicCid) { 2472 result_cid_(kDynamicCid) {
2589 ASSERT(value != NULL); 2473 ASSERT(value != NULL);
2590 ASSERT(type.IsZoneHandle()); // May be null if field is not an instance. 2474 ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
2591 inputs_[0] = value; 2475 inputs_[0] = value;
2592 } 2476 }
2593 2477
2594 DECLARE_COMPUTATION(LoadVMField) 2478 DECLARE_INSTRUCTION(LoadVMField)
2479 virtual RawAbstractType* CompileType() const;
2595 2480
2596 Value* value() const { return inputs_[0]; } 2481 Value* value() const { return inputs_[0]; }
2597 intptr_t offset_in_bytes() const { return offset_in_bytes_; } 2482 intptr_t offset_in_bytes() const { return offset_in_bytes_; }
2598 const AbstractType& type() const { return type_; } 2483 const AbstractType& type() const { return type_; }
2599 void set_result_cid(intptr_t value) { result_cid_ = value; } 2484 void set_result_cid(intptr_t value) { result_cid_ = value; }
2600 2485
2601 virtual void PrintOperandsTo(BufferFormatter* f) const; 2486 virtual void PrintOperandsTo(BufferFormatter* f) const;
2602 2487
2603 virtual bool CanDeoptimize() const { return false; } 2488 virtual bool CanDeoptimize() const { return false; }
2604 virtual intptr_t ResultCid() const { return result_cid_; } 2489 virtual intptr_t ResultCid() const { return result_cid_; }
2605 2490
2606 private: 2491 private:
2607 const intptr_t offset_in_bytes_; 2492 const intptr_t offset_in_bytes_;
2608 const AbstractType& type_; 2493 const AbstractType& type_;
2609 intptr_t result_cid_; 2494 intptr_t result_cid_;
2610 2495
2611 DISALLOW_COPY_AND_ASSIGN(LoadVMFieldComp); 2496 DISALLOW_COPY_AND_ASSIGN(LoadVMFieldInstr);
2612 }; 2497 };
2613 2498
2614 2499
2615 class StoreVMFieldComp : public TemplateComputation<2> { 2500 class StoreVMFieldInstr : public TemplateDefinition<2> {
2616 public: 2501 public:
2617 StoreVMFieldComp(Value* dest, 2502 StoreVMFieldInstr(Value* dest,
2618 intptr_t offset_in_bytes, 2503 intptr_t offset_in_bytes,
2619 Value* value, 2504 Value* value,
2620 const AbstractType& type) 2505 const AbstractType& type)
2621 : offset_in_bytes_(offset_in_bytes), type_(type) { 2506 : offset_in_bytes_(offset_in_bytes), type_(type) {
2622 ASSERT(value != NULL); 2507 ASSERT(value != NULL);
2623 ASSERT(dest != NULL); 2508 ASSERT(dest != NULL);
2624 ASSERT(type.IsZoneHandle()); // May be null if field is not an instance. 2509 ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
2625 inputs_[0] = value; 2510 inputs_[0] = value;
2626 inputs_[1] = dest; 2511 inputs_[1] = dest;
2627 } 2512 }
2628 2513
2629 DECLARE_COMPUTATION(StoreVMField) 2514 DECLARE_INSTRUCTION(StoreVMField)
2515 virtual RawAbstractType* CompileType() const;
2630 2516
2631 Value* value() const { return inputs_[0]; } 2517 Value* value() const { return inputs_[0]; }
2632 Value* dest() const { return inputs_[1]; } 2518 Value* dest() const { return inputs_[1]; }
2633 intptr_t offset_in_bytes() const { return offset_in_bytes_; } 2519 intptr_t offset_in_bytes() const { return offset_in_bytes_; }
2634 const AbstractType& type() const { return type_; } 2520 const AbstractType& type() const { return type_; }
2635 2521
2636 virtual void PrintOperandsTo(BufferFormatter* f) const; 2522 virtual void PrintOperandsTo(BufferFormatter* f) const;
2637 2523
2638 virtual bool CanDeoptimize() const { return false; } 2524 virtual bool CanDeoptimize() const { return false; }
2639 virtual intptr_t ResultCid() const { return kDynamicCid; } 2525 virtual intptr_t ResultCid() const { return kDynamicCid; }
2640 2526
2641 private: 2527 private:
2642 const intptr_t offset_in_bytes_; 2528 const intptr_t offset_in_bytes_;
2643 const AbstractType& type_; 2529 const AbstractType& type_;
2644 2530
2645 DISALLOW_COPY_AND_ASSIGN(StoreVMFieldComp); 2531 DISALLOW_COPY_AND_ASSIGN(StoreVMFieldInstr);
2646 }; 2532 };
2647 2533
2648 2534
2649 class InstantiateTypeArgumentsComp : public TemplateComputation<1> { 2535 class InstantiateTypeArgumentsInstr : public TemplateDefinition<1> {
2650 public: 2536 public:
2651 InstantiateTypeArgumentsComp(intptr_t token_pos, 2537 InstantiateTypeArgumentsInstr(intptr_t token_pos,
2652 const AbstractTypeArguments& type_arguments, 2538 const AbstractTypeArguments& type_arguments,
2653 Value* instantiator) 2539 Value* instantiator)
2654 : token_pos_(token_pos), 2540 : token_pos_(token_pos),
2655 type_arguments_(type_arguments) { 2541 type_arguments_(type_arguments) {
2656 ASSERT(type_arguments.IsZoneHandle()); 2542 ASSERT(type_arguments.IsZoneHandle());
2657 ASSERT(instantiator != NULL); 2543 ASSERT(instantiator != NULL);
2658 inputs_[0] = instantiator; 2544 inputs_[0] = instantiator;
2659 } 2545 }
2660 2546
2661 DECLARE_COMPUTATION(InstantiateTypeArguments) 2547 DECLARE_INSTRUCTION(InstantiateTypeArguments)
2548 virtual RawAbstractType* CompileType() const;
2662 2549
2663 Value* instantiator() const { return inputs_[0]; } 2550 Value* instantiator() const { return inputs_[0]; }
2664 const AbstractTypeArguments& type_arguments() const { 2551 const AbstractTypeArguments& type_arguments() const {
2665 return type_arguments_; 2552 return type_arguments_;
2666 } 2553 }
2667 intptr_t token_pos() const { return token_pos_; } 2554 intptr_t token_pos() const { return token_pos_; }
2668 2555
2669 virtual void PrintOperandsTo(BufferFormatter* f) const; 2556 virtual void PrintOperandsTo(BufferFormatter* f) const;
2670 2557
2671 virtual bool CanDeoptimize() const { return false; } 2558 virtual bool CanDeoptimize() const { return false; }
2672 virtual intptr_t ResultCid() const { return kDynamicCid; } 2559 virtual intptr_t ResultCid() const { return kDynamicCid; }
2673 2560
2674 private: 2561 private:
2675 const intptr_t token_pos_; 2562 const intptr_t token_pos_;
2676 const AbstractTypeArguments& type_arguments_; 2563 const AbstractTypeArguments& type_arguments_;
2677 2564
2678 DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsComp); 2565 DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsInstr);
2679 }; 2566 };
2680 2567
2681 2568
2682 class ExtractConstructorTypeArgumentsComp : public TemplateComputation<1> { 2569 class ExtractConstructorTypeArgumentsInstr : public TemplateDefinition<1> {
2683 public: 2570 public:
2684 ExtractConstructorTypeArgumentsComp( 2571 ExtractConstructorTypeArgumentsInstr(
2685 intptr_t token_pos, 2572 intptr_t token_pos,
2686 const AbstractTypeArguments& type_arguments, 2573 const AbstractTypeArguments& type_arguments,
2687 Value* instantiator) 2574 Value* instantiator)
2688 : token_pos_(token_pos), 2575 : token_pos_(token_pos),
2689 type_arguments_(type_arguments) { 2576 type_arguments_(type_arguments) {
2690 ASSERT(instantiator != NULL); 2577 ASSERT(instantiator != NULL);
2691 inputs_[0] = instantiator; 2578 inputs_[0] = instantiator;
2692 } 2579 }
2693 2580
2694 DECLARE_COMPUTATION(ExtractConstructorTypeArguments) 2581 DECLARE_INSTRUCTION(ExtractConstructorTypeArguments)
2582 virtual RawAbstractType* CompileType() const;
2695 2583
2696 Value* instantiator() const { return inputs_[0]; } 2584 Value* instantiator() const { return inputs_[0]; }
2697 const AbstractTypeArguments& type_arguments() const { 2585 const AbstractTypeArguments& type_arguments() const {
2698 return type_arguments_; 2586 return type_arguments_;
2699 } 2587 }
2700 intptr_t token_pos() const { return token_pos_; } 2588 intptr_t token_pos() const { return token_pos_; }
2701 2589
2702 virtual void PrintOperandsTo(BufferFormatter* f) const; 2590 virtual void PrintOperandsTo(BufferFormatter* f) const;
2703 2591
2704 virtual bool CanDeoptimize() const { return false; } 2592 virtual bool CanDeoptimize() const { return false; }
2705 virtual intptr_t ResultCid() const { return kDynamicCid; } 2593 virtual intptr_t ResultCid() const { return kDynamicCid; }
2706 2594
2707 private: 2595 private:
2708 const intptr_t token_pos_; 2596 const intptr_t token_pos_;
2709 const AbstractTypeArguments& type_arguments_; 2597 const AbstractTypeArguments& type_arguments_;
2710 2598
2711 DISALLOW_COPY_AND_ASSIGN(ExtractConstructorTypeArgumentsComp); 2599 DISALLOW_COPY_AND_ASSIGN(ExtractConstructorTypeArgumentsInstr);
2712 }; 2600 };
2713 2601
2714 2602
2715 class ExtractConstructorInstantiatorComp : public TemplateComputation<1> { 2603 class ExtractConstructorInstantiatorInstr : public TemplateDefinition<1> {
2716 public: 2604 public:
2717 ExtractConstructorInstantiatorComp(ConstructorCallNode* ast_node, 2605 ExtractConstructorInstantiatorInstr(ConstructorCallNode* ast_node,
2718 Value* instantiator) 2606 Value* instantiator)
2719 : ast_node_(*ast_node) { 2607 : ast_node_(*ast_node) {
2720 ASSERT(instantiator != NULL); 2608 ASSERT(instantiator != NULL);
2721 inputs_[0] = instantiator; 2609 inputs_[0] = instantiator;
2722 } 2610 }
2723 2611
2724 DECLARE_COMPUTATION(ExtractConstructorInstantiator) 2612 DECLARE_INSTRUCTION(ExtractConstructorInstantiator)
2613 virtual RawAbstractType* CompileType() const;
2725 2614
2726 Value* instantiator() const { return inputs_[0]; } 2615 Value* instantiator() const { return inputs_[0]; }
2727 const AbstractTypeArguments& type_arguments() const { 2616 const AbstractTypeArguments& type_arguments() const {
2728 return ast_node_.type_arguments(); 2617 return ast_node_.type_arguments();
2729 } 2618 }
2730 const Function& constructor() const { return ast_node_.constructor(); } 2619 const Function& constructor() const { return ast_node_.constructor(); }
2731 intptr_t token_pos() const { return ast_node_.token_pos(); } 2620 intptr_t token_pos() const { return ast_node_.token_pos(); }
2732 2621
2733 virtual bool CanDeoptimize() const { return false; } 2622 virtual bool CanDeoptimize() const { return false; }
2734 virtual intptr_t ResultCid() const { return kDynamicCid; } 2623 virtual intptr_t ResultCid() const { return kDynamicCid; }
2735 2624
2736 private: 2625 private:
2737 const ConstructorCallNode& ast_node_; 2626 const ConstructorCallNode& ast_node_;
2738 2627
2739 DISALLOW_COPY_AND_ASSIGN(ExtractConstructorInstantiatorComp); 2628 DISALLOW_COPY_AND_ASSIGN(ExtractConstructorInstantiatorInstr);
2740 }; 2629 };
2741 2630
2742 2631
2743 class AllocateContextComp : public TemplateComputation<0> { 2632 class AllocateContextInstr : public TemplateDefinition<0> {
2744 public: 2633 public:
2745 AllocateContextComp(intptr_t token_pos, 2634 AllocateContextInstr(intptr_t token_pos,
2746 intptr_t num_context_variables) 2635 intptr_t num_context_variables)
2747 : token_pos_(token_pos), 2636 : token_pos_(token_pos),
2748 num_context_variables_(num_context_variables) {} 2637 num_context_variables_(num_context_variables) {}
2749 2638
2750 DECLARE_COMPUTATION(AllocateContext); 2639 DECLARE_INSTRUCTION(AllocateContext);
2640 virtual RawAbstractType* CompileType() const;
2751 2641
2752 intptr_t token_pos() const { return token_pos_; } 2642 intptr_t token_pos() const { return token_pos_; }
2753 intptr_t num_context_variables() const { return num_context_variables_; } 2643 intptr_t num_context_variables() const { return num_context_variables_; }
2754 2644
2755 virtual void PrintOperandsTo(BufferFormatter* f) const; 2645 virtual void PrintOperandsTo(BufferFormatter* f) const;
2756 2646
2757 virtual bool CanDeoptimize() const { return false; } 2647 virtual bool CanDeoptimize() const { return false; }
2758 virtual intptr_t ResultCid() const { return kDynamicCid; } 2648 virtual intptr_t ResultCid() const { return kDynamicCid; }
2759 2649
2760 private: 2650 private:
2761 const intptr_t token_pos_; 2651 const intptr_t token_pos_;
2762 const intptr_t num_context_variables_; 2652 const intptr_t num_context_variables_;
2763 2653
2764 DISALLOW_COPY_AND_ASSIGN(AllocateContextComp); 2654 DISALLOW_COPY_AND_ASSIGN(AllocateContextInstr);
2765 }; 2655 };
2766 2656
2767 2657
2768 class ChainContextComp : public TemplateComputation<1> { 2658 class ChainContextInstr : public TemplateDefinition<1> {
2769 public: 2659 public:
2770 explicit ChainContextComp(Value* context_value) { 2660 explicit ChainContextInstr(Value* context_value) {
2771 ASSERT(context_value != NULL); 2661 ASSERT(context_value != NULL);
2772 inputs_[0] = context_value; 2662 inputs_[0] = context_value;
2773 } 2663 }
2774 2664
2775 DECLARE_COMPUTATION(ChainContext) 2665 DECLARE_INSTRUCTION(ChainContext)
2666 virtual RawAbstractType* CompileType() const;
2776 2667
2777 Value* context_value() const { return inputs_[0]; } 2668 Value* context_value() const { return inputs_[0]; }
2778 2669
2779 virtual bool CanDeoptimize() const { return false; } 2670 virtual bool CanDeoptimize() const { return false; }
2780 virtual intptr_t ResultCid() const { return kIllegalCid; } 2671 virtual intptr_t ResultCid() const { return kIllegalCid; }
2781 2672
2782 private: 2673 private:
2783 DISALLOW_COPY_AND_ASSIGN(ChainContextComp); 2674 DISALLOW_COPY_AND_ASSIGN(ChainContextInstr);
2784 }; 2675 };
2785 2676
2786 2677
2787 class CloneContextComp : public TemplateComputation<1> { 2678 class CloneContextInstr : public TemplateDefinition<1> {
2788 public: 2679 public:
2789 CloneContextComp(intptr_t token_pos, 2680 CloneContextInstr(intptr_t token_pos, Value* context_value)
2790 Value* context_value)
2791 : token_pos_(token_pos) { 2681 : token_pos_(token_pos) {
2792 ASSERT(context_value != NULL); 2682 ASSERT(context_value != NULL);
2793 inputs_[0] = context_value; 2683 inputs_[0] = context_value;
2794 } 2684 }
2795 2685
2796 intptr_t token_pos() const { return token_pos_; } 2686 intptr_t token_pos() const { return token_pos_; }
2797 Value* context_value() const { return inputs_[0]; } 2687 Value* context_value() const { return inputs_[0]; }
2798 2688
2799 DECLARE_COMPUTATION(CloneContext) 2689 DECLARE_INSTRUCTION(CloneContext)
2690 virtual RawAbstractType* CompileType() const;
2800 2691
2801 virtual bool CanDeoptimize() const { return false; } 2692 virtual bool CanDeoptimize() const { return false; }
2802 virtual intptr_t ResultCid() const { return kIllegalCid; } 2693 virtual intptr_t ResultCid() const { return kIllegalCid; }
2803 2694
2804 private: 2695 private:
2805 const intptr_t token_pos_; 2696 const intptr_t token_pos_;
2806 2697
2807 DISALLOW_COPY_AND_ASSIGN(CloneContextComp); 2698 DISALLOW_COPY_AND_ASSIGN(CloneContextInstr);
2808 }; 2699 };
2809 2700
2810 2701
2811 class CatchEntryComp : public TemplateComputation<0> { 2702 class CatchEntryInstr : public TemplateDefinition<0> {
2812 public: 2703 public:
2813 CatchEntryComp(const LocalVariable& exception_var, 2704 CatchEntryInstr(const LocalVariable& exception_var,
2814 const LocalVariable& stacktrace_var) 2705 const LocalVariable& stacktrace_var)
2815 : exception_var_(exception_var), stacktrace_var_(stacktrace_var) {} 2706 : exception_var_(exception_var), stacktrace_var_(stacktrace_var) {}
2816 2707
2817 const LocalVariable& exception_var() const { return exception_var_; } 2708 const LocalVariable& exception_var() const { return exception_var_; }
2818 const LocalVariable& stacktrace_var() const { return stacktrace_var_; } 2709 const LocalVariable& stacktrace_var() const { return stacktrace_var_; }
2819 2710
2820 DECLARE_COMPUTATION(CatchEntry) 2711 DECLARE_INSTRUCTION(CatchEntry)
2712 virtual RawAbstractType* CompileType() const;
2821 2713
2822 virtual void PrintOperandsTo(BufferFormatter* f) const; 2714 virtual void PrintOperandsTo(BufferFormatter* f) const;
2823 2715
2824 virtual bool CanDeoptimize() const { return false; } 2716 virtual bool CanDeoptimize() const { return false; }
2825 virtual intptr_t ResultCid() const { return kIllegalCid; } 2717 virtual intptr_t ResultCid() const { return kIllegalCid; }
2826 2718
2827 private: 2719 private:
2828 const LocalVariable& exception_var_; 2720 const LocalVariable& exception_var_;
2829 const LocalVariable& stacktrace_var_; 2721 const LocalVariable& stacktrace_var_;
2830 2722
2831 DISALLOW_COPY_AND_ASSIGN(CatchEntryComp); 2723 DISALLOW_COPY_AND_ASSIGN(CatchEntryInstr);
2832 }; 2724 };
2833 2725
2834 2726
2835 class CheckEitherNonSmiComp : public TemplateComputation<2> { 2727 class CheckEitherNonSmiInstr : public TemplateDefinition<2> {
2836 public: 2728 public:
2837 CheckEitherNonSmiComp(Value* left, 2729 CheckEitherNonSmiInstr(Value* left,
2838 Value* right, 2730 Value* right,
2839 InstanceCallComp* instance_call) 2731 InstanceCallInstr* instance_call) {
2840 : instance_call_(instance_call) {
2841 ASSERT(left != NULL); 2732 ASSERT(left != NULL);
2842 ASSERT(right != NULL); 2733 ASSERT(right != NULL);
2843 inputs_[0] = left; 2734 inputs_[0] = left;
2844 inputs_[1] = right; 2735 inputs_[1] = right;
2736 deopt_id_ = instance_call->deopt_id();
2845 } 2737 }
2846 2738
2847 DECLARE_COMPUTATION(CheckEitherNonSmi) 2739 DECLARE_INSTRUCTION(CheckEitherNonSmi)
2740 virtual RawAbstractType* CompileType() const;
2848 2741
2849 virtual bool CanDeoptimize() const { return true; } 2742 virtual bool CanDeoptimize() const { return true; }
2850 virtual intptr_t ResultCid() const { return kIllegalCid; } 2743 virtual intptr_t ResultCid() const { return kIllegalCid; }
2851 2744
2852 virtual bool AttributesEqual(Computation* other) const { return true; } 2745 virtual bool AttributesEqual(Definition* other) const { return true; }
2853 2746
2854 virtual bool HasSideEffect() const { return false; } 2747 virtual bool HasSideEffect() const { return false; }
2855 2748
2856 Value* left() const { return inputs_[0]; } 2749 Value* left() const { return inputs_[0]; }
2857 2750
2858 Value* right() const { return inputs_[1]; } 2751 Value* right() const { return inputs_[1]; }
2859 2752
2860 virtual Definition* TryReplace(BindInstr* instr) const; 2753 virtual Definition* Canonicalize();
2861 2754
2862 private: 2755 private:
2863 InstanceCallComp* instance_call_; 2756 DISALLOW_COPY_AND_ASSIGN(CheckEitherNonSmiInstr);
2864
2865 DISALLOW_COPY_AND_ASSIGN(CheckEitherNonSmiComp);
2866 }; 2757 };
2867 2758
2868 2759
2869 class BoxDoubleComp : public TemplateComputation<1> { 2760 class BoxDoubleInstr : public TemplateDefinition<1> {
2870 public: 2761 public:
2871 BoxDoubleComp(Value* value, InstanceCallComp* instance_call) 2762 BoxDoubleInstr(Value* value, InstanceCallInstr* instance_call)
2872 : token_pos_((instance_call != NULL) ? instance_call->token_pos() : 0) { 2763 : token_pos_((instance_call != NULL) ? instance_call->token_pos() : 0) {
2873 ASSERT(value != NULL); 2764 ASSERT(value != NULL);
2874 inputs_[0] = value; 2765 inputs_[0] = value;
2875 } 2766 }
2876 2767
2877 Value* value() const { return inputs_[0]; } 2768 Value* value() const { return inputs_[0]; }
2878 2769
2879 intptr_t token_pos() const { return token_pos_; } 2770 intptr_t token_pos() const { return token_pos_; }
2880 2771
2881 virtual bool CanDeoptimize() const { return false; } 2772 virtual bool CanDeoptimize() const { return false; }
2882 virtual bool HasSideEffect() const { return false; } 2773 virtual bool HasSideEffect() const { return false; }
2883 virtual bool AttributesEqual(Computation* other) const { return true; } 2774 virtual bool AttributesEqual(Definition* other) const { return true; }
2884 2775
2885 virtual intptr_t ResultCid() const; 2776 virtual intptr_t ResultCid() const;
2886 2777
2887 virtual Representation RequiredInputRepresentation(intptr_t idx) const { 2778 virtual Representation RequiredInputRepresentation(intptr_t idx) const {
2888 ASSERT(idx == 0); 2779 ASSERT(idx == 0);
2889 return kUnboxedDouble; 2780 return kUnboxedDouble;
2890 } 2781 }
2891 2782
2892 DECLARE_COMPUTATION(BoxDouble) 2783 DECLARE_INSTRUCTION(BoxDouble)
2784 virtual RawAbstractType* CompileType() const;
2893 2785
2894 private: 2786 private:
2895 const intptr_t token_pos_; 2787 const intptr_t token_pos_;
2896 2788
2897 DISALLOW_COPY_AND_ASSIGN(BoxDoubleComp); 2789 DISALLOW_COPY_AND_ASSIGN(BoxDoubleInstr);
2898 }; 2790 };
2899 2791
2900 2792
2901 class UnboxDoubleComp : public TemplateComputation<1> { 2793 class UnboxDoubleInstr : public TemplateDefinition<1> {
2902 public: 2794 public:
2903 UnboxDoubleComp(Value* value, intptr_t deopt_id) 2795 UnboxDoubleInstr(Value* value, intptr_t deopt_id) {
2904 : deopt_id_(deopt_id) {
2905 ASSERT(value != NULL); 2796 ASSERT(value != NULL);
2906 inputs_[0] = value; 2797 inputs_[0] = value;
2798 deopt_id_ = deopt_id;
2907 } 2799 }
2908 2800
2909 Value* value() const { return inputs_[0]; } 2801 Value* value() const { return inputs_[0]; }
2910 2802
2911 virtual bool CanDeoptimize() const { 2803 virtual bool CanDeoptimize() const {
2912 return value()->ResultCid() != kDoubleCid; 2804 return value()->ResultCid() != kDoubleCid;
2913 } 2805 }
2914 2806
2915 // The output is not an instance but when it is boxed it becomes double. 2807 // The output is not an instance but when it is boxed it becomes double.
2916 virtual intptr_t ResultCid() const { return kDoubleCid; } 2808 virtual intptr_t ResultCid() const { return kDoubleCid; }
2917 2809
2918 virtual Representation representation() const { 2810 virtual Representation representation() const {
2919 return kUnboxedDouble; 2811 return kUnboxedDouble;
2920 } 2812 }
2921 2813
2922 virtual bool HasSideEffect() const { return false; } 2814 virtual bool HasSideEffect() const { return false; }
2923 virtual bool AttributesEqual(Computation* other) const { return true; } 2815 virtual bool AttributesEqual(Definition* other) const { return true; }
2924 2816
2925 DECLARE_COMPUTATION(UnboxDouble) 2817 DECLARE_INSTRUCTION(UnboxDouble)
2818 virtual RawAbstractType* CompileType() const;
2926 2819
2927 private: 2820 private:
2928 const intptr_t deopt_id_; 2821 DISALLOW_COPY_AND_ASSIGN(UnboxDoubleInstr);
2929
2930 DISALLOW_COPY_AND_ASSIGN(UnboxDoubleComp);
2931 }; 2822 };
2932 2823
2933 2824
2934 class UnboxedDoubleBinaryOpComp : public TemplateComputation<2> { 2825 class UnboxedDoubleBinaryOpInstr : public TemplateDefinition<2> {
2935 public: 2826 public:
2936 UnboxedDoubleBinaryOpComp(Token::Kind op_kind, 2827 UnboxedDoubleBinaryOpInstr(Token::Kind op_kind,
2937 Value* left, 2828 Value* left,
2938 Value* right, 2829 Value* right,
2939 InstanceCallComp* call) 2830 InstanceCallInstr* instance_call)
2940 : op_kind_(op_kind), deopt_id_(call->deopt_id()) { 2831 : op_kind_(op_kind) {
2941 ASSERT(left != NULL); 2832 ASSERT(left != NULL);
2942 ASSERT(right != NULL); 2833 ASSERT(right != NULL);
2943 inputs_[0] = left; 2834 inputs_[0] = left;
2944 inputs_[1] = right; 2835 inputs_[1] = right;
2836 deopt_id_ = instance_call->deopt_id();
2945 } 2837 }
2946 2838
2947 Value* left() const { return inputs_[0]; } 2839 Value* left() const { return inputs_[0]; }
2948 Value* right() const { return inputs_[1]; } 2840 Value* right() const { return inputs_[1]; }
2949 2841
2950 Token::Kind op_kind() const { return op_kind_; } 2842 Token::Kind op_kind() const { return op_kind_; }
2951 2843
2952 virtual void PrintOperandsTo(BufferFormatter* f) const; 2844 virtual void PrintOperandsTo(BufferFormatter* f) const;
2953 2845
2954 virtual bool CanDeoptimize() const { return false; } 2846 virtual bool CanDeoptimize() const { return false; }
2955 virtual bool HasSideEffect() const { return false; } 2847 virtual bool HasSideEffect() const { return false; }
2956 2848
2957 virtual bool AttributesEqual(Computation* other) const { 2849 virtual bool AttributesEqual(Definition* other) const {
2958 return op_kind() == other->AsUnboxedDoubleBinaryOp()->op_kind(); 2850 return op_kind() == other->AsUnboxedDoubleBinaryOp()->op_kind();
2959 } 2851 }
2960 2852
2961 // The output is not an instance but when it is boxed it becomes double. 2853 // The output is not an instance but when it is boxed it becomes double.
2962 virtual intptr_t ResultCid() const { return kDoubleCid; } 2854 virtual intptr_t ResultCid() const { return kDoubleCid; }
2963 2855
2964 virtual Representation representation() const { 2856 virtual Representation representation() const {
2965 return kUnboxedDouble; 2857 return kUnboxedDouble;
2966 } 2858 }
2967 2859
2968 virtual Representation RequiredInputRepresentation(intptr_t idx) const { 2860 virtual Representation RequiredInputRepresentation(intptr_t idx) const {
2969 ASSERT((idx == 0) || (idx == 1)); 2861 ASSERT((idx == 0) || (idx == 1));
2970 return kUnboxedDouble; 2862 return kUnboxedDouble;
2971 } 2863 }
2972 2864
2973 virtual intptr_t DeoptimizationTarget() const { 2865 virtual intptr_t DeoptimizationTarget() const {
2974 return deopt_id_; 2866 return deopt_id();
2975 } 2867 }
2976 2868
2977 DECLARE_COMPUTATION(UnboxedDoubleBinaryOp) 2869 DECLARE_INSTRUCTION(UnboxedDoubleBinaryOp)
2870 virtual RawAbstractType* CompileType() const;
2978 2871
2979 private: 2872 private:
2980 const Token::Kind op_kind_; 2873 const Token::Kind op_kind_;
2981 const intptr_t deopt_id_;
2982 2874
2983 DISALLOW_COPY_AND_ASSIGN(UnboxedDoubleBinaryOpComp); 2875 DISALLOW_COPY_AND_ASSIGN(UnboxedDoubleBinaryOpInstr);
2984 }; 2876 };
2985 2877
2986 2878
2987 class BinarySmiOpComp : public TemplateComputation<2> { 2879 class BinarySmiOpInstr : public TemplateDefinition<2> {
2988 public: 2880 public:
2989 BinarySmiOpComp(Token::Kind op_kind, 2881 BinarySmiOpInstr(Token::Kind op_kind,
2990 InstanceCallComp* instance_call, 2882 InstanceCallInstr* instance_call,
2991 Value* left, 2883 Value* left,
2992 Value* right) 2884 Value* right)
2993 : op_kind_(op_kind), 2885 : op_kind_(op_kind),
2994 instance_call_(instance_call) { 2886 instance_call_(instance_call) {
2995 ASSERT(left != NULL); 2887 ASSERT(left != NULL);
2996 ASSERT(right != NULL); 2888 ASSERT(right != NULL);
2997 inputs_[0] = left; 2889 inputs_[0] = left;
2998 inputs_[1] = right; 2890 inputs_[1] = right;
2999 } 2891 }
3000 2892
3001 Value* left() const { return inputs_[0]; } 2893 Value* left() const { return inputs_[0]; }
3002 Value* right() const { return inputs_[1]; } 2894 Value* right() const { return inputs_[1]; }
3003 2895
3004 Token::Kind op_kind() const { return op_kind_; } 2896 Token::Kind op_kind() const { return op_kind_; }
3005 2897
3006 InstanceCallComp* instance_call() const { return instance_call_; } 2898 InstanceCallInstr* instance_call() const { return instance_call_; }
3007 2899
3008 const ICData* ic_data() const { return instance_call()->ic_data(); } 2900 const ICData* ic_data() const { return instance_call()->ic_data(); }
3009 2901
3010 virtual void PrintOperandsTo(BufferFormatter* f) const; 2902 virtual void PrintOperandsTo(BufferFormatter* f) const;
3011 2903
3012 DECLARE_COMPUTATION(BinarySmiOp) 2904 DECLARE_INSTRUCTION(BinarySmiOp)
2905 virtual RawAbstractType* CompileType() const;
3013 2906
3014 virtual bool CanDeoptimize() const; 2907 virtual bool CanDeoptimize() const;
3015 2908
3016 virtual intptr_t ResultCid() const; 2909 virtual intptr_t ResultCid() const;
3017 2910
3018 private: 2911 private:
3019 const Token::Kind op_kind_; 2912 const Token::Kind op_kind_;
3020 InstanceCallComp* instance_call_; 2913 InstanceCallInstr* instance_call_;
3021 2914
3022 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpComp); 2915 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr);
3023 }; 2916 };
3024 2917
3025 2918
3026 class BinaryMintOpComp : public TemplateComputation<2> { 2919 class BinaryMintOpInstr : public TemplateDefinition<2> {
3027 public: 2920 public:
3028 BinaryMintOpComp(Token::Kind op_kind, 2921 BinaryMintOpInstr(Token::Kind op_kind,
3029 InstanceCallComp* instance_call, 2922 InstanceCallInstr* instance_call,
3030 Value* left, 2923 Value* left,
3031 Value* right) 2924 Value* right)
3032 : op_kind_(op_kind), 2925 : op_kind_(op_kind),
3033 instance_call_(instance_call) { 2926 instance_call_(instance_call) {
3034 ASSERT(left != NULL); 2927 ASSERT(left != NULL);
3035 ASSERT(right != NULL); 2928 ASSERT(right != NULL);
3036 inputs_[0] = left; 2929 inputs_[0] = left;
3037 inputs_[1] = right; 2930 inputs_[1] = right;
3038 } 2931 }
3039 2932
3040 Value* left() const { return inputs_[0]; } 2933 Value* left() const { return inputs_[0]; }
3041 Value* right() const { return inputs_[1]; } 2934 Value* right() const { return inputs_[1]; }
3042 2935
3043 Token::Kind op_kind() const { return op_kind_; } 2936 Token::Kind op_kind() const { return op_kind_; }
3044 2937
3045 InstanceCallComp* instance_call() const { return instance_call_; } 2938 InstanceCallInstr* instance_call() const { return instance_call_; }
3046 2939
3047 const ICData* ic_data() const { return instance_call()->ic_data(); } 2940 const ICData* ic_data() const { return instance_call()->ic_data(); }
3048 2941
3049 virtual void PrintOperandsTo(BufferFormatter* f) const; 2942 virtual void PrintOperandsTo(BufferFormatter* f) const;
3050 2943
3051 DECLARE_COMPUTATION(BinaryMintOp) 2944 DECLARE_INSTRUCTION(BinaryMintOp)
2945 virtual RawAbstractType* CompileType() const;
3052 2946
3053 virtual bool CanDeoptimize() const { return true; } 2947 virtual bool CanDeoptimize() const { return true; }
3054 virtual intptr_t ResultCid() const; 2948 virtual intptr_t ResultCid() const;
3055 2949
3056 private: 2950 private:
3057 const Token::Kind op_kind_; 2951 const Token::Kind op_kind_;
3058 InstanceCallComp* instance_call_; 2952 InstanceCallInstr* instance_call_;
3059 2953
3060 DISALLOW_COPY_AND_ASSIGN(BinaryMintOpComp); 2954 DISALLOW_COPY_AND_ASSIGN(BinaryMintOpInstr);
3061 }; 2955 };
3062 2956
3063 2957
3064 // Handles both Smi operations: BIT_OR and NEGATE. 2958 // Handles both Smi operations: BIT_OR and NEGATE.
3065 class UnarySmiOpComp : public TemplateComputation<1> { 2959 class UnarySmiOpInstr : public TemplateDefinition<1> {
3066 public: 2960 public:
3067 UnarySmiOpComp(Token::Kind op_kind, 2961 UnarySmiOpInstr(Token::Kind op_kind,
3068 InstanceCallComp* instance_call, 2962 InstanceCallInstr* instance_call,
3069 Value* value) 2963 Value* value)
3070 : op_kind_(op_kind), instance_call_(instance_call) { 2964 : op_kind_(op_kind), instance_call_(instance_call) {
3071 ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT)); 2965 ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT));
3072 ASSERT(value != NULL); 2966 ASSERT(value != NULL);
3073 inputs_[0] = value; 2967 inputs_[0] = value;
3074 } 2968 }
3075 2969
3076 Value* value() const { return inputs_[0]; } 2970 Value* value() const { return inputs_[0]; }
3077 Token::Kind op_kind() const { return op_kind_; } 2971 Token::Kind op_kind() const { return op_kind_; }
3078 2972
3079 InstanceCallComp* instance_call() const { return instance_call_; } 2973 InstanceCallInstr* instance_call() const { return instance_call_; }
3080 2974
3081 virtual void PrintOperandsTo(BufferFormatter* f) const; 2975 virtual void PrintOperandsTo(BufferFormatter* f) const;
3082 2976
3083 DECLARE_COMPUTATION(UnarySmiOp) 2977 DECLARE_INSTRUCTION(UnarySmiOp)
2978 virtual RawAbstractType* CompileType() const;
3084 2979
3085 virtual bool CanDeoptimize() const { return op_kind() == Token::kNEGATE; } 2980 virtual bool CanDeoptimize() const { return op_kind() == Token::kNEGATE; }
3086 virtual intptr_t ResultCid() const { return kSmiCid; } 2981 virtual intptr_t ResultCid() const { return kSmiCid; }
3087 2982
3088 private: 2983 private:
3089 const Token::Kind op_kind_; 2984 const Token::Kind op_kind_;
3090 InstanceCallComp* instance_call_; 2985 InstanceCallInstr* instance_call_;
3091 2986
3092 DISALLOW_COPY_AND_ASSIGN(UnarySmiOpComp); 2987 DISALLOW_COPY_AND_ASSIGN(UnarySmiOpInstr);
3093 }; 2988 };
3094 2989
3095 2990
3096 // Handles non-Smi NEGATE operations 2991 // Handles non-Smi NEGATE operations
3097 class NumberNegateComp : public TemplateComputation<1> { 2992 class NumberNegateInstr : public TemplateDefinition<1> {
3098 public: 2993 public:
3099 NumberNegateComp(InstanceCallComp* instance_call, 2994 NumberNegateInstr(InstanceCallInstr* instance_call, Value* value)
3100 Value* value) : instance_call_(instance_call) { 2995 : instance_call_(instance_call) {
3101 ASSERT(value != NULL); 2996 ASSERT(value != NULL);
3102 inputs_[0] = value; 2997 inputs_[0] = value;
3103 } 2998 }
3104 2999
3105 Value* value() const { return inputs_[0]; } 3000 Value* value() const { return inputs_[0]; }
3106 3001
3107 InstanceCallComp* instance_call() const { return instance_call_; } 3002 InstanceCallInstr* instance_call() const { return instance_call_; }
3108 3003
3109 const ICData* ic_data() const { return instance_call()->ic_data(); } 3004 const ICData* ic_data() const { return instance_call()->ic_data(); }
3110 3005
3111 DECLARE_COMPUTATION(NumberNegate) 3006 DECLARE_INSTRUCTION(NumberNegate)
3007 virtual RawAbstractType* CompileType() const;
3112 3008
3113 virtual bool CanDeoptimize() const { return true; } 3009 virtual bool CanDeoptimize() const { return true; }
3114 virtual intptr_t ResultCid() const { return kDoubleCid; } 3010 virtual intptr_t ResultCid() const { return kDoubleCid; }
3115 3011
3116 private: 3012 private:
3117 InstanceCallComp* instance_call_; 3013 InstanceCallInstr* instance_call_;
3118 3014
3119 DISALLOW_COPY_AND_ASSIGN(NumberNegateComp); 3015 DISALLOW_COPY_AND_ASSIGN(NumberNegateInstr);
3120 }; 3016 };
3121 3017
3122 3018
3123 class CheckStackOverflowComp : public TemplateComputation<0> { 3019 class CheckStackOverflowInstr : public TemplateDefinition<0> {
3124 public: 3020 public:
3125 explicit CheckStackOverflowComp(intptr_t token_pos) 3021 explicit CheckStackOverflowInstr(intptr_t token_pos)
3126 : token_pos_(token_pos) {} 3022 : token_pos_(token_pos) {}
3127 3023
3128 intptr_t token_pos() const { return token_pos_; } 3024 intptr_t token_pos() const { return token_pos_; }
3129 3025
3130 DECLARE_COMPUTATION(CheckStackOverflow) 3026 DECLARE_INSTRUCTION(CheckStackOverflow)
3027 virtual RawAbstractType* CompileType() const;
3131 3028
3132 virtual bool CanDeoptimize() const { return false; } 3029 virtual bool CanDeoptimize() const { return false; }
3133 virtual intptr_t ResultCid() const { return kIllegalCid; } 3030 virtual intptr_t ResultCid() const { return kIllegalCid; }
3134 3031
3135 private: 3032 private:
3136 const intptr_t token_pos_; 3033 const intptr_t token_pos_;
3137 3034
3138 DISALLOW_COPY_AND_ASSIGN(CheckStackOverflowComp); 3035 DISALLOW_COPY_AND_ASSIGN(CheckStackOverflowInstr);
3139 }; 3036 };
3140 3037
3141 3038
3142 class DoubleToDoubleComp : public TemplateComputation<1> { 3039 class DoubleToDoubleInstr : public TemplateDefinition<1> {
3143 public: 3040 public:
3144 DoubleToDoubleComp(Value* value, InstanceCallComp* instance_call) 3041 DoubleToDoubleInstr(Value* value, InstanceCallInstr* instance_call)
3145 : instance_call_(instance_call) { 3042 : instance_call_(instance_call) {
3146 ASSERT(value != NULL); 3043 ASSERT(value != NULL);
3147 inputs_[0] = value; 3044 inputs_[0] = value;
3148 } 3045 }
3149 3046
3150 Value* value() const { return inputs_[0]; } 3047 Value* value() const { return inputs_[0]; }
3151 3048
3152 InstanceCallComp* instance_call() const { return instance_call_; } 3049 InstanceCallInstr* instance_call() const { return instance_call_; }
3153 3050
3154 DECLARE_COMPUTATION(DoubleToDouble) 3051 DECLARE_INSTRUCTION(DoubleToDouble)
3052 virtual RawAbstractType* CompileType() const;
3155 3053
3156 virtual bool CanDeoptimize() const { return true; } 3054 virtual bool CanDeoptimize() const { return true; }
3157 virtual intptr_t ResultCid() const { return kDoubleCid; } 3055 virtual intptr_t ResultCid() const { return kDoubleCid; }
3158 3056
3159 private: 3057 private:
3160 InstanceCallComp* instance_call_; 3058 InstanceCallInstr* instance_call_;
3161 3059
3162 DISALLOW_COPY_AND_ASSIGN(DoubleToDoubleComp); 3060 DISALLOW_COPY_AND_ASSIGN(DoubleToDoubleInstr);
3163 }; 3061 };
3164 3062
3165 3063
3166 class SmiToDoubleComp : public TemplateComputation<0> { 3064 class SmiToDoubleInstr : public TemplateDefinition<0> {
3167 public: 3065 public:
3168 explicit SmiToDoubleComp(InstanceCallComp* instance_call) 3066 explicit SmiToDoubleInstr(InstanceCallInstr* instance_call)
3169 : instance_call_(instance_call) { } 3067 : instance_call_(instance_call) { }
3170 3068
3171 InstanceCallComp* instance_call() const { return instance_call_; } 3069 InstanceCallInstr* instance_call() const { return instance_call_; }
3172 3070
3173 DECLARE_CALL_COMPUTATION(SmiToDouble) 3071 DECLARE_INSTRUCTION(SmiToDouble)
3072 virtual RawAbstractType* CompileType() const;
3174 3073
3175 virtual intptr_t ArgumentCount() const { return 1; } 3074 virtual intptr_t ArgumentCount() const { return 1; }
3176 3075
3177 virtual bool CanDeoptimize() const { return true; } 3076 virtual bool CanDeoptimize() const { return true; }
3178 virtual intptr_t ResultCid() const { return kDoubleCid; } 3077 virtual intptr_t ResultCid() const { return kDoubleCid; }
3179 3078
3180 private: 3079 private:
3181 InstanceCallComp* instance_call_; 3080 InstanceCallInstr* instance_call_;
3182 3081
3183 DISALLOW_COPY_AND_ASSIGN(SmiToDoubleComp); 3082 DISALLOW_COPY_AND_ASSIGN(SmiToDoubleInstr);
3184 }; 3083 };
3185 3084
3186 3085
3187 class CheckClassComp : public TemplateComputation<1> { 3086 class CheckClassInstr : public TemplateDefinition<1> {
3188 public: 3087 public:
3189 CheckClassComp(Value* value, 3088 CheckClassInstr(Value* value,
3190 InstanceCallComp* instance_call, 3089 InstanceCallInstr* instance_call,
3191 const ICData& unary_checks) 3090 const ICData& unary_checks)
3192 : instance_call_(instance_call), 3091 : unary_checks_(unary_checks) {
3193 unary_checks_(unary_checks) {
3194 ASSERT(value != NULL); 3092 ASSERT(value != NULL);
3195 inputs_[0] = value; 3093 inputs_[0] = value;
3094 deopt_id_ = instance_call->deopt_id();
3196 } 3095 }
3197 3096
3198 DECLARE_COMPUTATION(CheckClass) 3097 DECLARE_INSTRUCTION(CheckClass)
3098 virtual RawAbstractType* CompileType() const;
3199 3099
3200 virtual bool CanDeoptimize() const { return true; } 3100 virtual bool CanDeoptimize() const { return true; }
3201 virtual intptr_t ResultCid() const { return kIllegalCid; } 3101 virtual intptr_t ResultCid() const { return kIllegalCid; }
3202 3102
3203 virtual bool AttributesEqual(Computation* other) const; 3103 virtual bool AttributesEqual(Definition* other) const;
3204 3104
3205 virtual bool HasSideEffect() const { return false; } 3105 virtual bool HasSideEffect() const { return false; }
3206 3106
3207 Value* value() const { return inputs_[0]; } 3107 Value* value() const { return inputs_[0]; }
3208 3108
3209 const ICData& unary_checks() const { return unary_checks_; } 3109 const ICData& unary_checks() const { return unary_checks_; }
3210 3110
3211 virtual intptr_t deopt_id() const { return instance_call_->deopt_id(); } 3111 virtual Definition* Canonicalize();
3212
3213 virtual Definition* TryReplace(BindInstr* instr) const;
3214 3112
3215 virtual void PrintOperandsTo(BufferFormatter* f) const; 3113 virtual void PrintOperandsTo(BufferFormatter* f) const;
3216 3114
3217 private: 3115 private:
3218 InstanceCallComp* instance_call_;
3219 const ICData& unary_checks_; 3116 const ICData& unary_checks_;
3220 3117
3221 DISALLOW_COPY_AND_ASSIGN(CheckClassComp); 3118 DISALLOW_COPY_AND_ASSIGN(CheckClassInstr);
3222 }; 3119 };
3223 3120
3224 3121
3225 class CheckSmiComp : public TemplateComputation<1> { 3122 class CheckSmiInstr : public TemplateDefinition<1> {
3226 public: 3123 public:
3227 CheckSmiComp(Value* value, intptr_t original_deopt_id) 3124 CheckSmiInstr(Value* value, intptr_t original_deopt_id) {
3228 : original_deopt_id_(original_deopt_id) {
3229 ASSERT(value != NULL); 3125 ASSERT(value != NULL);
3230 ASSERT(original_deopt_id != Isolate::kNoDeoptId); 3126 ASSERT(original_deopt_id != Isolate::kNoDeoptId);
3231 inputs_[0] = value; 3127 inputs_[0] = value;
3128 deopt_id_ = original_deopt_id;
3232 } 3129 }
3233 3130
3234 DECLARE_COMPUTATION(CheckSmi) 3131 DECLARE_INSTRUCTION(CheckSmi)
3132 virtual RawAbstractType* CompileType() const;
3235 3133
3236 virtual bool CanDeoptimize() const { return true; } 3134 virtual bool CanDeoptimize() const { return true; }
3237 virtual intptr_t ResultCid() const { return kIllegalCid; } 3135 virtual intptr_t ResultCid() const { return kIllegalCid; }
3238 3136
3239 virtual bool AttributesEqual(Computation* other) const { return true; } 3137 virtual bool AttributesEqual(Definition* other) const { return true; }
3240 3138
3241 virtual bool HasSideEffect() const { return false; } 3139 virtual bool HasSideEffect() const { return false; }
3242 3140
3243 virtual Definition* TryReplace(BindInstr* instr) const; 3141 virtual Definition* Canonicalize();
3244 3142
3245 Value* value() const { return inputs_[0]; } 3143 Value* value() const { return inputs_[0]; }
3246 3144
3247 virtual intptr_t deopt_id() const { return original_deopt_id_; }
3248
3249 private: 3145 private:
3250 const intptr_t original_deopt_id_; 3146 DISALLOW_COPY_AND_ASSIGN(CheckSmiInstr);
3251
3252 DISALLOW_COPY_AND_ASSIGN(CheckSmiComp);
3253 }; 3147 };
3254 3148
3255 3149
3256 class CheckArrayBoundComp : public TemplateComputation<2> { 3150 class CheckArrayBoundInstr : public TemplateDefinition<2> {
3257 public: 3151 public:
3258 CheckArrayBoundComp(Value* array, 3152 CheckArrayBoundInstr(Value* array,
3259 Value* index, 3153 Value* index,
3260 intptr_t array_type, 3154 intptr_t array_type,
3261 InstanceCallComp* instance_call) 3155 InstanceCallInstr* instance_call)
3262 : array_type_(array_type), instance_call_(instance_call) { 3156 : array_type_(array_type) {
3263 ASSERT(array != NULL); 3157 ASSERT(array != NULL);
3264 ASSERT(index != NULL); 3158 ASSERT(index != NULL);
3265 inputs_[0] = array; 3159 inputs_[0] = array;
3266 inputs_[1] = index; 3160 inputs_[1] = index;
3161 deopt_id_ = instance_call->deopt_id();
3267 } 3162 }
3268 3163
3269 DECLARE_COMPUTATION(CheckArrayBound) 3164 DECLARE_INSTRUCTION(CheckArrayBound)
3165 virtual RawAbstractType* CompileType() const;
3270 3166
3271 virtual bool CanDeoptimize() const { return true; } 3167 virtual bool CanDeoptimize() const { return true; }
3272 virtual intptr_t ResultCid() const { return kIllegalCid; } 3168 virtual intptr_t ResultCid() const { return kIllegalCid; }
3273 3169
3274 virtual bool AttributesEqual(Computation* other) const; 3170 virtual bool AttributesEqual(Definition* other) const;
3275 3171
3276 virtual bool HasSideEffect() const { return false; } 3172 virtual bool HasSideEffect() const { return false; }
3277 3173
3278 Value* array() const { return inputs_[0]; } 3174 Value* array() const { return inputs_[0]; }
3279 Value* index() const { return inputs_[1]; } 3175 Value* index() const { return inputs_[1]; }
3280 3176
3281 intptr_t array_type() const { return array_type_; } 3177 intptr_t array_type() const { return array_type_; }
3282 3178
3283 virtual intptr_t deopt_id() const { return instance_call_->deopt_id(); }
3284
3285 private: 3179 private:
3286 intptr_t array_type_; 3180 intptr_t array_type_;
3287 InstanceCallComp* instance_call_;
3288 3181
3289 DISALLOW_COPY_AND_ASSIGN(CheckArrayBoundComp); 3182 DISALLOW_COPY_AND_ASSIGN(CheckArrayBoundInstr);
3290 }; 3183 };
3291 3184
3292 3185
3293 #undef DECLARE_COMPUTATION 3186 #undef DECLARE_INSTRUCTION
3294
3295
3296 // Implementation of type testers and cast functins.
3297 #define DEFINE_COMPUTATION_PREDICATE(ShortName, ClassName) \
3298 bool Computation::Is##ShortName() const { \
3299 return computation_kind() == k##ShortName; \
3300 } \
3301 const ClassName* Computation::As##ShortName() const { \
3302 if (!Is##ShortName()) return NULL; \
3303 return static_cast<const ClassName*>(this); \
3304 } \
3305 ClassName* Computation::As##ShortName() { \
3306 if (!Is##ShortName()) return NULL; \
3307 return static_cast<ClassName*>(this); \
3308 }
3309 FOR_EACH_COMPUTATION(DEFINE_COMPUTATION_PREDICATE)
3310 #undef DEFINE_COMPUTATION_PREDICATE
3311 3187
3312 3188
3313 class Environment : public ZoneAllocated { 3189 class Environment : public ZoneAllocated {
3314 public: 3190 public:
3315 // Construct an environment by constructing uses from an array of definitions. 3191 // Construct an environment by constructing uses from an array of definitions.
3316 Environment(const GrowableArray<Definition*>& definitions, 3192 Environment(const GrowableArray<Definition*>& definitions,
3317 intptr_t fixed_parameter_count); 3193 intptr_t fixed_parameter_count);
3318 3194
3319 void set_locations(Location* locations) { 3195 void set_locations(Location* locations) {
3320 ASSERT(locations_ == NULL); 3196 ASSERT(locations_ == NULL);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3370 virtual ~FlowGraphVisitor() { } 3246 virtual ~FlowGraphVisitor() { }
3371 3247
3372 ForwardInstructionIterator* current_iterator() const { 3248 ForwardInstructionIterator* current_iterator() const {
3373 return current_iterator_; 3249 return current_iterator_;
3374 } 3250 }
3375 3251
3376 // Visit each block in the block order, and for each block its 3252 // Visit each block in the block order, and for each block its
3377 // instructions in order from the block entry to exit. 3253 // instructions in order from the block entry to exit.
3378 virtual void VisitBlocks(); 3254 virtual void VisitBlocks();
3379 3255
3380 // Visit functions for instruction and computation classes, with empty 3256 // Visit functions for instruction classes, with an empty default
3381 // default implementations. 3257 // implementation.
3382 #define DECLARE_VISIT_COMPUTATION(ShortName, ClassName) \
3383 virtual void Visit##ShortName(ClassName* comp, BindInstr* instr) { }
3384
3385 #define DECLARE_VISIT_INSTRUCTION(ShortName) \ 3258 #define DECLARE_VISIT_INSTRUCTION(ShortName) \
3386 virtual void Visit##ShortName(ShortName##Instr* instr) { } 3259 virtual void Visit##ShortName(ShortName##Instr* instr) { }
3387 3260
3388 FOR_EACH_COMPUTATION(DECLARE_VISIT_COMPUTATION)
3389 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 3261 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
3390 3262
3391 #undef DECLARE_VISIT_COMPUTATION
3392 #undef DECLARE_VISIT_INSTRUCTION 3263 #undef DECLARE_VISIT_INSTRUCTION
3393 3264
3394 protected: 3265 protected:
3395 const GrowableArray<BlockEntryInstr*>& block_order_; 3266 const GrowableArray<BlockEntryInstr*>& block_order_;
3396 ForwardInstructionIterator* current_iterator_; 3267 ForwardInstructionIterator* current_iterator_;
3397 3268
3398 private: 3269 private:
3399 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); 3270 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor);
3400 }; 3271 };
3401 3272
3402 3273
3403 } // namespace dart 3274 } // namespace dart
3404 3275
3405 #endif // VM_INTERMEDIATE_LANGUAGE_H_ 3276 #endif // VM_INTERMEDIATE_LANGUAGE_H_
OLDNEW
« no previous file with comments | « runtime/vm/il_printer.cc ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698