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

Side by Side Diff: src/codegen.h

Issue 3169049: Remove dependence of code-stubs on codegen, the virtual frame code generator.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 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 | « src/code-stubs.h ('k') | src/debug.h » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 // CheckForInlineRuntimeCall 66 // CheckForInlineRuntimeCall
67 // PatchInlineRuntimeEntry 67 // PatchInlineRuntimeEntry
68 // AnalyzeCondition 68 // AnalyzeCondition
69 // CodeForFunctionPosition 69 // CodeForFunctionPosition
70 // CodeForReturnPosition 70 // CodeForReturnPosition
71 // CodeForStatementPosition 71 // CodeForStatementPosition
72 // CodeForDoWhileConditionPosition 72 // CodeForDoWhileConditionPosition
73 // CodeForSourcePosition 73 // CodeForSourcePosition
74 74
75 75
76 // Mode to overwrite BinaryExpression values.
77 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
78 enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
79
80 // Types of uncatchable exceptions.
81 enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
82
83 #define INLINE_RUNTIME_FUNCTION_LIST(F) \ 76 #define INLINE_RUNTIME_FUNCTION_LIST(F) \
84 F(IsSmi, 1, 1) \ 77 F(IsSmi, 1, 1) \
85 F(IsNonNegativeSmi, 1, 1) \ 78 F(IsNonNegativeSmi, 1, 1) \
86 F(IsArray, 1, 1) \ 79 F(IsArray, 1, 1) \
87 F(IsRegExp, 1, 1) \ 80 F(IsRegExp, 1, 1) \
88 F(CallFunction, -1 /* receiver + n args + function */, 1) \ 81 F(CallFunction, -1 /* receiver + n args + function */, 1) \
89 F(IsConstructCall, 0, 1) \ 82 F(IsConstructCall, 0, 1) \
90 F(ArgumentsLength, 0, 1) \ 83 F(ArgumentsLength, 0, 1) \
91 F(Arguments, 1, 1) \ 84 F(Arguments, 1, 1) \
92 F(ClassOf, 1, 1) \ 85 F(ClassOf, 1, 1) \
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 #include "mips/codegen-mips.h" 124 #include "mips/codegen-mips.h"
132 #else 125 #else
133 #error Unsupported target architecture. 126 #error Unsupported target architecture.
134 #endif 127 #endif
135 128
136 #include "register-allocator.h" 129 #include "register-allocator.h"
137 130
138 namespace v8 { 131 namespace v8 {
139 namespace internal { 132 namespace internal {
140 133
141 // Support for "structured" code comments.
142 #ifdef DEBUG
143
144 class Comment BASE_EMBEDDED {
145 public:
146 Comment(MacroAssembler* masm, const char* msg);
147 ~Comment();
148
149 private:
150 MacroAssembler* masm_;
151 const char* msg_;
152 };
153
154 #else
155
156 class Comment BASE_EMBEDDED {
157 public:
158 Comment(MacroAssembler*, const char*) {}
159 };
160
161 #endif // DEBUG
162
163
164 // Code generation can be nested. Code generation scopes form a stack 134 // Code generation can be nested. Code generation scopes form a stack
165 // of active code generators. 135 // of active code generators.
166 class CodeGeneratorScope BASE_EMBEDDED { 136 class CodeGeneratorScope BASE_EMBEDDED {
167 public: 137 public:
168 explicit CodeGeneratorScope(CodeGenerator* cgen) { 138 explicit CodeGeneratorScope(CodeGenerator* cgen) {
169 previous_ = top_; 139 previous_ = top_;
170 top_ = cgen; 140 top_ = cgen;
171 } 141 }
172 142
173 ~CodeGeneratorScope() { 143 ~CodeGeneratorScope() {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 VirtualFrame frame_; 196 VirtualFrame frame_;
227 }; 197 };
228 198
229 #else 199 #else
230 200
231 #error Unsupported target architecture. 201 #error Unsupported target architecture.
232 202
233 #endif 203 #endif
234 204
235 205
236 // Helper interface to prepare to/restore after making runtime calls.
237 class RuntimeCallHelper {
238 public:
239 virtual ~RuntimeCallHelper() {}
240
241 virtual void BeforeCall(MacroAssembler* masm) const = 0;
242
243 virtual void AfterCall(MacroAssembler* masm) const = 0;
244
245 protected:
246 RuntimeCallHelper() {}
247
248 private:
249 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
250 };
251
252
253 // RuntimeCallHelper implementation that saves/restores state of a 206 // RuntimeCallHelper implementation that saves/restores state of a
254 // virtual frame. 207 // virtual frame.
255 class VirtualFrameRuntimeCallHelper : public RuntimeCallHelper { 208 class VirtualFrameRuntimeCallHelper : public RuntimeCallHelper {
256 public: 209 public:
257 // Does not take ownership of |frame_state|. 210 // Does not take ownership of |frame_state|.
258 explicit VirtualFrameRuntimeCallHelper(const FrameRegisterState* frame_state) 211 explicit VirtualFrameRuntimeCallHelper(const FrameRegisterState* frame_state)
259 : frame_state_(frame_state) {} 212 : frame_state_(frame_state) {}
260 213
261 virtual void BeforeCall(MacroAssembler* masm) const; 214 virtual void BeforeCall(MacroAssembler* masm) const;
262 215
263 virtual void AfterCall(MacroAssembler* masm) const; 216 virtual void AfterCall(MacroAssembler* masm) const;
264 217
265 private: 218 private:
266 const FrameRegisterState* frame_state_; 219 const FrameRegisterState* frame_state_;
267 }; 220 };
268 221
269 222
270 // RuntimeCallHelper implementation used in IC stubs: enters/leaves a
271 // newly created internal frame before/after the runtime call.
272 class ICRuntimeCallHelper : public RuntimeCallHelper {
273 public:
274 ICRuntimeCallHelper() {}
275
276 virtual void BeforeCall(MacroAssembler* masm) const;
277
278 virtual void AfterCall(MacroAssembler* masm) const;
279 };
280
281
282 // Trivial RuntimeCallHelper implementation.
283 class NopRuntimeCallHelper : public RuntimeCallHelper {
284 public:
285 NopRuntimeCallHelper() {}
286
287 virtual void BeforeCall(MacroAssembler* masm) const {}
288
289 virtual void AfterCall(MacroAssembler* masm) const {}
290 };
291
292
293 // Deferred code objects are small pieces of code that are compiled 223 // Deferred code objects are small pieces of code that are compiled
294 // out of line. They are used to defer the compilation of uncommon 224 // out of line. They are used to defer the compilation of uncommon
295 // paths thereby avoiding expensive jumps around uncommon code parts. 225 // paths thereby avoiding expensive jumps around uncommon code parts.
296 class DeferredCode: public ZoneObject { 226 class DeferredCode: public ZoneObject {
297 public: 227 public:
298 DeferredCode(); 228 DeferredCode();
299 virtual ~DeferredCode() { } 229 virtual ~DeferredCode() { }
300 230
301 virtual void Generate() = 0; 231 virtual void Generate() = 0;
302 232
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 Label exit_label_; 275 Label exit_label_;
346 276
347 FrameRegisterState frame_state_; 277 FrameRegisterState frame_state_;
348 278
349 #ifdef DEBUG 279 #ifdef DEBUG
350 const char* comment_; 280 const char* comment_;
351 #endif 281 #endif
352 DISALLOW_COPY_AND_ASSIGN(DeferredCode); 282 DISALLOW_COPY_AND_ASSIGN(DeferredCode);
353 }; 283 };
354 284
355 class StackCheckStub : public CodeStub {
356 public:
357 StackCheckStub() { }
358 285
359 void Generate(MacroAssembler* masm); 286 } } // namespace v8::internal
360
361 private:
362
363 const char* GetName() { return "StackCheckStub"; }
364
365 Major MajorKey() { return StackCheck; }
366 int MinorKey() { return 0; }
367 };
368
369
370 class FastNewClosureStub : public CodeStub {
371 public:
372 void Generate(MacroAssembler* masm);
373
374 private:
375 const char* GetName() { return "FastNewClosureStub"; }
376 Major MajorKey() { return FastNewClosure; }
377 int MinorKey() { return 0; }
378 };
379
380
381 class FastNewContextStub : public CodeStub {
382 public:
383 static const int kMaximumSlots = 64;
384
385 explicit FastNewContextStub(int slots) : slots_(slots) {
386 ASSERT(slots_ > 0 && slots <= kMaximumSlots);
387 }
388
389 void Generate(MacroAssembler* masm);
390
391 private:
392 int slots_;
393
394 const char* GetName() { return "FastNewContextStub"; }
395 Major MajorKey() { return FastNewContext; }
396 int MinorKey() { return slots_; }
397 };
398
399
400 class FastCloneShallowArrayStub : public CodeStub {
401 public:
402 // Maximum length of copied elements array.
403 static const int kMaximumClonedLength = 8;
404
405 enum Mode {
406 CLONE_ELEMENTS,
407 COPY_ON_WRITE_ELEMENTS
408 };
409
410 FastCloneShallowArrayStub(Mode mode, int length)
411 : mode_(mode),
412 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
413 ASSERT(length_ >= 0);
414 ASSERT(length_ <= kMaximumClonedLength);
415 }
416
417 void Generate(MacroAssembler* masm);
418
419 private:
420 Mode mode_;
421 int length_;
422
423 const char* GetName() { return "FastCloneShallowArrayStub"; }
424 Major MajorKey() { return FastCloneShallowArray; }
425 int MinorKey() {
426 ASSERT(mode_ == 0 || mode_ == 1);
427 return (length_ << 1) | mode_;
428 }
429 };
430
431
432 class InstanceofStub: public CodeStub {
433 public:
434 InstanceofStub() { }
435
436 void Generate(MacroAssembler* masm);
437
438 private:
439 Major MajorKey() { return Instanceof; }
440 int MinorKey() { return 0; }
441 };
442
443
444 enum NegativeZeroHandling {
445 kStrictNegativeZero,
446 kIgnoreNegativeZero
447 };
448
449
450 class GenericUnaryOpStub : public CodeStub {
451 public:
452 GenericUnaryOpStub(Token::Value op,
453 UnaryOverwriteMode overwrite,
454 NegativeZeroHandling negative_zero = kStrictNegativeZero)
455 : op_(op), overwrite_(overwrite), negative_zero_(negative_zero) { }
456
457 private:
458 Token::Value op_;
459 UnaryOverwriteMode overwrite_;
460 NegativeZeroHandling negative_zero_;
461
462 class OverwriteField: public BitField<UnaryOverwriteMode, 0, 1> {};
463 class NegativeZeroField: public BitField<NegativeZeroHandling, 1, 1> {};
464 class OpField: public BitField<Token::Value, 2, kMinorBits - 2> {};
465
466 Major MajorKey() { return GenericUnaryOp; }
467 int MinorKey() {
468 return OpField::encode(op_) |
469 OverwriteField::encode(overwrite_) |
470 NegativeZeroField::encode(negative_zero_);
471 }
472
473 void Generate(MacroAssembler* masm);
474
475 const char* GetName();
476 };
477
478
479 enum NaNInformation {
480 kBothCouldBeNaN,
481 kCantBothBeNaN
482 };
483
484
485 class CompareStub: public CodeStub {
486 public:
487 CompareStub(Condition cc,
488 bool strict,
489 NaNInformation nan_info = kBothCouldBeNaN,
490 bool include_number_compare = true,
491 Register lhs = no_reg,
492 Register rhs = no_reg) :
493 cc_(cc),
494 strict_(strict),
495 never_nan_nan_(nan_info == kCantBothBeNaN),
496 include_number_compare_(include_number_compare),
497 lhs_(lhs),
498 rhs_(rhs),
499 name_(NULL) { }
500
501 void Generate(MacroAssembler* masm);
502
503 private:
504 Condition cc_;
505 bool strict_;
506 // Only used for 'equal' comparisons. Tells the stub that we already know
507 // that at least one side of the comparison is not NaN. This allows the
508 // stub to use object identity in the positive case. We ignore it when
509 // generating the minor key for other comparisons to avoid creating more
510 // stubs.
511 bool never_nan_nan_;
512 // Do generate the number comparison code in the stub. Stubs without number
513 // comparison code is used when the number comparison has been inlined, and
514 // the stub will be called if one of the operands is not a number.
515 bool include_number_compare_;
516 // Register holding the left hand side of the comparison if the stub gives
517 // a choice, no_reg otherwise.
518 Register lhs_;
519 // Register holding the right hand side of the comparison if the stub gives
520 // a choice, no_reg otherwise.
521 Register rhs_;
522
523 // Encoding of the minor key CCCCCCCCCCCCRCNS.
524 class StrictField: public BitField<bool, 0, 1> {};
525 class NeverNanNanField: public BitField<bool, 1, 1> {};
526 class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
527 class RegisterField: public BitField<bool, 3, 1> {};
528 class ConditionField: public BitField<int, 4, 12> {};
529
530 Major MajorKey() { return Compare; }
531
532 int MinorKey();
533
534 // Branch to the label if the given object isn't a symbol.
535 void BranchIfNonSymbol(MacroAssembler* masm,
536 Label* label,
537 Register object,
538 Register scratch);
539
540 // Unfortunately you have to run without snapshots to see most of these
541 // names in the profile since most compare stubs end up in the snapshot.
542 char* name_;
543 const char* GetName();
544 #ifdef DEBUG
545 void Print() {
546 PrintF("CompareStub (cc %d), (strict %s), "
547 "(never_nan_nan %s), (number_compare %s) ",
548 static_cast<int>(cc_),
549 strict_ ? "true" : "false",
550 never_nan_nan_ ? "true" : "false",
551 include_number_compare_ ? "included" : "not included");
552
553 if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) {
554 PrintF("(lhs r%d), (rhs r%d)\n", lhs_.code(), rhs_.code());
555 } else {
556 PrintF("\n");
557 }
558 }
559 #endif
560 };
561
562
563 class CEntryStub : public CodeStub {
564 public:
565 explicit CEntryStub(int result_size) : result_size_(result_size) { }
566
567 void Generate(MacroAssembler* masm);
568
569 private:
570 void GenerateCore(MacroAssembler* masm,
571 Label* throw_normal_exception,
572 Label* throw_termination_exception,
573 Label* throw_out_of_memory_exception,
574 bool do_gc,
575 bool always_allocate_scope,
576 int alignment_skew = 0);
577 void GenerateThrowTOS(MacroAssembler* masm);
578 void GenerateThrowUncatchable(MacroAssembler* masm,
579 UncatchableExceptionType type);
580
581 // Number of pointers/values returned.
582 const int result_size_;
583
584 // Minor key encoding
585 class IndirectResultBits: public BitField<bool, 1, 1> {};
586
587 Major MajorKey() { return CEntry; }
588 // Minor key must differ if different result_size_ values means different
589 // code is generated.
590 int MinorKey();
591
592 const char* GetName() { return "CEntryStub"; }
593 };
594
595
596 class ApiGetterEntryStub : public CodeStub {
597 public:
598 ApiGetterEntryStub(Handle<AccessorInfo> info,
599 ApiFunction* fun)
600 : info_(info),
601 fun_(fun) { }
602 void Generate(MacroAssembler* masm);
603 virtual bool has_custom_cache() { return true; }
604 virtual bool GetCustomCache(Code** code_out);
605 virtual void SetCustomCache(Code* value);
606
607 static const int kStackSpace = 5;
608 static const int kArgc = 4;
609 private:
610 Handle<AccessorInfo> info() { return info_; }
611 ApiFunction* fun() { return fun_; }
612 Major MajorKey() { return NoCache; }
613 int MinorKey() { return 0; }
614 const char* GetName() { return "ApiEntryStub"; }
615 // The accessor info associated with the function.
616 Handle<AccessorInfo> info_;
617 // The function to be called.
618 ApiFunction* fun_;
619 };
620
621
622 class JSEntryStub : public CodeStub {
623 public:
624 JSEntryStub() { }
625
626 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
627
628 protected:
629 void GenerateBody(MacroAssembler* masm, bool is_construct);
630
631 private:
632 Major MajorKey() { return JSEntry; }
633 int MinorKey() { return 0; }
634
635 const char* GetName() { return "JSEntryStub"; }
636 };
637
638
639 class JSConstructEntryStub : public JSEntryStub {
640 public:
641 JSConstructEntryStub() { }
642
643 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
644
645 private:
646 int MinorKey() { return 1; }
647
648 const char* GetName() { return "JSConstructEntryStub"; }
649 };
650
651
652 class ArgumentsAccessStub: public CodeStub {
653 public:
654 enum Type {
655 READ_ELEMENT,
656 NEW_OBJECT
657 };
658
659 explicit ArgumentsAccessStub(Type type) : type_(type) { }
660
661 private:
662 Type type_;
663
664 Major MajorKey() { return ArgumentsAccess; }
665 int MinorKey() { return type_; }
666
667 void Generate(MacroAssembler* masm);
668 void GenerateReadElement(MacroAssembler* masm);
669 void GenerateNewObject(MacroAssembler* masm);
670
671 const char* GetName() { return "ArgumentsAccessStub"; }
672
673 #ifdef DEBUG
674 void Print() {
675 PrintF("ArgumentsAccessStub (type %d)\n", type_);
676 }
677 #endif
678 };
679
680
681 class RegExpExecStub: public CodeStub {
682 public:
683 RegExpExecStub() { }
684
685 private:
686 Major MajorKey() { return RegExpExec; }
687 int MinorKey() { return 0; }
688
689 void Generate(MacroAssembler* masm);
690
691 const char* GetName() { return "RegExpExecStub"; }
692
693 #ifdef DEBUG
694 void Print() {
695 PrintF("RegExpExecStub\n");
696 }
697 #endif
698 };
699
700
701 class CallFunctionStub: public CodeStub {
702 public:
703 CallFunctionStub(int argc, InLoopFlag in_loop, CallFunctionFlags flags)
704 : argc_(argc), in_loop_(in_loop), flags_(flags) { }
705
706 void Generate(MacroAssembler* masm);
707
708 private:
709 int argc_;
710 InLoopFlag in_loop_;
711 CallFunctionFlags flags_;
712
713 #ifdef DEBUG
714 void Print() {
715 PrintF("CallFunctionStub (args %d, in_loop %d, flags %d)\n",
716 argc_,
717 static_cast<int>(in_loop_),
718 static_cast<int>(flags_));
719 }
720 #endif
721
722 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
723 class InLoopBits: public BitField<InLoopFlag, 0, 1> {};
724 class FlagBits: public BitField<CallFunctionFlags, 1, 1> {};
725 class ArgcBits: public BitField<int, 2, 32 - 2> {};
726
727 Major MajorKey() { return CallFunction; }
728 int MinorKey() {
729 // Encode the parameters in a unique 32 bit value.
730 return InLoopBits::encode(in_loop_)
731 | FlagBits::encode(flags_)
732 | ArgcBits::encode(argc_);
733 }
734
735 InLoopFlag InLoop() { return in_loop_; }
736 bool ReceiverMightBeValue() {
737 return (flags_ & RECEIVER_MIGHT_BE_VALUE) != 0;
738 }
739
740 public:
741 static int ExtractArgcFromMinorKey(int minor_key) {
742 return ArgcBits::decode(minor_key);
743 }
744 };
745
746
747 enum StringIndexFlags {
748 // Accepts smis or heap numbers.
749 STRING_INDEX_IS_NUMBER,
750
751 // Accepts smis or heap numbers that are valid array indices
752 // (ECMA-262 15.4). Invalid indices are reported as being out of
753 // range.
754 STRING_INDEX_IS_ARRAY_INDEX
755 };
756
757
758 // Generates code implementing String.prototype.charCodeAt.
759 //
760 // Only supports the case when the receiver is a string and the index
761 // is a number (smi or heap number) that is a valid index into the
762 // string. Additional index constraints are specified by the
763 // flags. Otherwise, bails out to the provided labels.
764 //
765 // Register usage: |object| may be changed to another string in a way
766 // that doesn't affect charCodeAt/charAt semantics, |index| is
767 // preserved, |scratch| and |result| are clobbered.
768 class StringCharCodeAtGenerator {
769 public:
770 StringCharCodeAtGenerator(Register object,
771 Register index,
772 Register scratch,
773 Register result,
774 Label* receiver_not_string,
775 Label* index_not_number,
776 Label* index_out_of_range,
777 StringIndexFlags index_flags)
778 : object_(object),
779 index_(index),
780 scratch_(scratch),
781 result_(result),
782 receiver_not_string_(receiver_not_string),
783 index_not_number_(index_not_number),
784 index_out_of_range_(index_out_of_range),
785 index_flags_(index_flags) {
786 ASSERT(!scratch_.is(object_));
787 ASSERT(!scratch_.is(index_));
788 ASSERT(!scratch_.is(result_));
789 ASSERT(!result_.is(object_));
790 ASSERT(!result_.is(index_));
791 }
792
793 // Generates the fast case code. On the fallthrough path |result|
794 // register contains the result.
795 void GenerateFast(MacroAssembler* masm);
796
797 // Generates the slow case code. Must not be naturally
798 // reachable. Expected to be put after a ret instruction (e.g., in
799 // deferred code). Always jumps back to the fast case.
800 void GenerateSlow(MacroAssembler* masm,
801 const RuntimeCallHelper& call_helper);
802
803 private:
804 Register object_;
805 Register index_;
806 Register scratch_;
807 Register result_;
808
809 Label* receiver_not_string_;
810 Label* index_not_number_;
811 Label* index_out_of_range_;
812
813 StringIndexFlags index_flags_;
814
815 Label call_runtime_;
816 Label index_not_smi_;
817 Label got_smi_index_;
818 Label exit_;
819
820 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
821 };
822
823
824 // Generates code for creating a one-char string from a char code.
825 class StringCharFromCodeGenerator {
826 public:
827 StringCharFromCodeGenerator(Register code,
828 Register result)
829 : code_(code),
830 result_(result) {
831 ASSERT(!code_.is(result_));
832 }
833
834 // Generates the fast case code. On the fallthrough path |result|
835 // register contains the result.
836 void GenerateFast(MacroAssembler* masm);
837
838 // Generates the slow case code. Must not be naturally
839 // reachable. Expected to be put after a ret instruction (e.g., in
840 // deferred code). Always jumps back to the fast case.
841 void GenerateSlow(MacroAssembler* masm,
842 const RuntimeCallHelper& call_helper);
843
844 private:
845 Register code_;
846 Register result_;
847
848 Label slow_case_;
849 Label exit_;
850
851 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
852 };
853
854
855 // Generates code implementing String.prototype.charAt.
856 //
857 // Only supports the case when the receiver is a string and the index
858 // is a number (smi or heap number) that is a valid index into the
859 // string. Additional index constraints are specified by the
860 // flags. Otherwise, bails out to the provided labels.
861 //
862 // Register usage: |object| may be changed to another string in a way
863 // that doesn't affect charCodeAt/charAt semantics, |index| is
864 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
865 class StringCharAtGenerator {
866 public:
867 StringCharAtGenerator(Register object,
868 Register index,
869 Register scratch1,
870 Register scratch2,
871 Register result,
872 Label* receiver_not_string,
873 Label* index_not_number,
874 Label* index_out_of_range,
875 StringIndexFlags index_flags)
876 : char_code_at_generator_(object,
877 index,
878 scratch1,
879 scratch2,
880 receiver_not_string,
881 index_not_number,
882 index_out_of_range,
883 index_flags),
884 char_from_code_generator_(scratch2, result) {}
885
886 // Generates the fast case code. On the fallthrough path |result|
887 // register contains the result.
888 void GenerateFast(MacroAssembler* masm);
889
890 // Generates the slow case code. Must not be naturally
891 // reachable. Expected to be put after a ret instruction (e.g., in
892 // deferred code). Always jumps back to the fast case.
893 void GenerateSlow(MacroAssembler* masm,
894 const RuntimeCallHelper& call_helper);
895
896 private:
897 StringCharCodeAtGenerator char_code_at_generator_;
898 StringCharFromCodeGenerator char_from_code_generator_;
899
900 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
901 };
902
903
904 } // namespace internal
905 } // namespace v8
906 287
907 #endif // V8_CODEGEN_H_ 288 #endif // V8_CODEGEN_H_
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/debug.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698