Chromium Code Reviews| Index: src/codegen.h |
| diff --git a/src/codegen.h b/src/codegen.h |
| index 358c6fccd3239cca4021f99c40f8cbd9e0a7b6f9..17017904c925b121a0301223929d2e731bc09624 100644 |
| --- a/src/codegen.h |
| +++ b/src/codegen.h |
| @@ -110,8 +110,9 @@ namespace internal { |
| F(ClassOf, 1, 1) \ |
| F(ValueOf, 1, 1) \ |
| F(SetValueOf, 2, 1) \ |
| - F(FastCharCodeAt, 2, 1) \ |
| - F(CharFromCode, 1, 1) \ |
| + F(StringCharCodeAt, 2, 1) \ |
| + F(StringCharFromCode, 1, 1) \ |
| + F(StringCharAt, 2, 1) \ |
| F(ObjectEquals, 2, 1) \ |
| F(Log, 3, 1) \ |
| F(RandomHeapNumber, 0, 1) \ |
| @@ -179,6 +180,95 @@ class CodeGeneratorScope BASE_EMBEDDED { |
| }; |
| +// State of used registers in a virtual frame. |
| +class FrameRegisterState { |
| + public: |
| + // Captures the current state of the given frame. |
| + explicit FrameRegisterState(VirtualFrame* frame); |
| + |
| + // Saves the state in the stack. |
| + void Save(MacroAssembler* masm) const; |
| + |
| + // Restores the state from the stack. |
| + void Restore(MacroAssembler* masm) const; |
| + |
| + private: |
| + // Constants indicating special actions. They should not be multiples |
| + // of kPointerSize so they will not collide with valid offsets from |
| + // the frame pointer. |
| + static const int kIgnore = -1; |
| + static const int kPush = 1; |
| + |
| + // This flag is ored with a valid offset from the frame pointer, so |
| + // it should fit in the low zero bits of a valid offset. |
| + static const int kSyncedFlag = 2; |
| + |
| + // C++ doesn't allow zero length arrays, so we make the array length 1 even |
| + // if we don't need it. |
| + static const int kRegistersArrayLength = |
| + (RegisterAllocator::kNumRegisters == 0) ? |
| + 1 : RegisterAllocator::kNumRegisters; |
| + int registers_[kRegistersArrayLength]; |
| +}; |
| + |
| + |
| +// Helper interface to prepare to/restore after making runtime calls. |
| +class RuntimeCallHelper { |
| + public: |
| + virtual ~RuntimeCallHelper() {} |
| + |
| + virtual void BeforeCall(MacroAssembler* masm) const = 0; |
| + |
| + virtual void AfterCall(MacroAssembler* masm) const = 0; |
| + |
| + protected: |
| + RuntimeCallHelper() {} |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper); |
| +}; |
| + |
| + |
| +// RuntimeCallHelper implementation that saves/restores state of a |
| +// virtual frame. |
| +class VirtualFrameRuntimeCallHelper : public RuntimeCallHelper { |
| + public: |
| + // Does not take ownership of |frame_state|. |
| + explicit VirtualFrameRuntimeCallHelper(const FrameRegisterState* frame_state) |
| + : frame_state_(frame_state) {} |
| + |
| + virtual void BeforeCall(MacroAssembler* masm) const; |
| + |
| + virtual void AfterCall(MacroAssembler* masm) const; |
| + |
| + private: |
| + const FrameRegisterState* frame_state_; |
| +}; |
| + |
| + |
| +// RuntimeCallHelper implementation used in IC stubs: enters/leaves a |
| +// newly created internal frame before/after the runtime call. |
| +class ICRuntimeCallHelper : public RuntimeCallHelper { |
| + public: |
| + ICRuntimeCallHelper() {} |
| + |
| + virtual void BeforeCall(MacroAssembler* masm) const; |
| + |
| + virtual void AfterCall(MacroAssembler* masm) const; |
| +}; |
| + |
| + |
| +// Trivial RuntimeCallHelper implementation. |
| +class NopRuntimeCallHelper : public RuntimeCallHelper { |
| + public: |
| + NopRuntimeCallHelper() {} |
| + |
| + virtual void BeforeCall(MacroAssembler* masm) const {} |
| + |
| + virtual void AfterCall(MacroAssembler* masm) const {} |
| +}; |
| + |
| + |
| // Deferred code objects are small pieces of code that are compiled |
| // out of line. They are used to defer the compilation of uncommon |
| // paths thereby avoiding expensive jumps around uncommon code parts. |
| @@ -209,6 +299,8 @@ class DeferredCode: public ZoneObject { |
| inline void Branch(Condition cc); |
| void BindExit() { masm_->bind(&exit_label_); } |
| + const FrameRegisterState* frame_state() const { return &frame_state_; } |
| + |
| void SaveRegisters(); |
| void RestoreRegisters(); |
| @@ -216,28 +308,13 @@ class DeferredCode: public ZoneObject { |
| MacroAssembler* masm_; |
| private: |
| - // Constants indicating special actions. They should not be multiples |
| - // of kPointerSize so they will not collide with valid offsets from |
| - // the frame pointer. |
| - static const int kIgnore = -1; |
| - static const int kPush = 1; |
| - |
| - // This flag is ored with a valid offset from the frame pointer, so |
| - // it should fit in the low zero bits of a valid offset. |
| - static const int kSyncedFlag = 2; |
| - |
| int statement_position_; |
| int position_; |
| Label entry_label_; |
| Label exit_label_; |
| - // C++ doesn't allow zero length arrays, so we make the array length 1 even |
| - // if we don't need it. |
| - static const int kRegistersArrayLength = |
| - (RegisterAllocator::kNumRegisters == 0) ? |
| - 1 : RegisterAllocator::kNumRegisters; |
| - int registers_[kRegistersArrayLength]; |
| + FrameRegisterState frame_state_; |
| #ifdef DEBUG |
| const char* comment_; |
| @@ -611,6 +688,161 @@ class ToBooleanStub: public CodeStub { |
| }; |
| +enum StringIndexFlags { |
|
Mads Ager (chromium)
2010/05/26 09:17:07
How about renaming these to something like:
INDEX
|
| + // Accepts smis or heap numbers. |
| + STRING_ANY_NUMBER_INDEX, |
| + |
| + // Accepts smis or heap numbers that are valid array indices |
| + // (ECMA-262 15.4). Invalid indices are reported as being out of |
| + // range. |
| + STRING_REQUIRE_ARRAY_INDEX |
| +}; |
| + |
| + |
| +// Generates code implementing String.prototype.charCodeAt. |
| +// |
| +// Only supports the case when the receiver is a string and the index |
| +// is a number (smi or heap number) that is a valid index into the |
| +// string. Otherwise, bails out to the provided labels. |
| +// |
| +// Register usage: |object| may be changed to another string in a way |
| +// that doesn't affect charCodeAt/charAt semantics, |index| is |
| +// preserved, |scratch| and |result| are clobbered. |
| +class StringCharCodeAtGenerator { |
| + public: |
| + StringCharCodeAtGenerator(Register object, |
| + Register index, |
| + Register scratch, |
| + Register result, |
| + Label* receiver_not_string, |
| + Label* index_not_number, |
| + Label* index_out_of_range, |
| + StringIndexFlags index_flags) |
| + : object_(object), |
| + index_(index), |
| + scratch_(scratch), |
| + result_(result), |
| + receiver_not_string_(receiver_not_string), |
| + index_not_number_(index_not_number), |
| + index_out_of_range_(index_out_of_range), |
| + index_flags_(index_flags) { |
| + ASSERT(!scratch_.is(object_)); |
| + ASSERT(!scratch_.is(index_)); |
| + ASSERT(!scratch_.is(result_)); |
| + ASSERT(!result_.is(object_)); |
| + ASSERT(!result_.is(index_)); |
| + } |
| + |
| + // Generates the fast case code. On the fallthrough path |result| |
| + // register contains the result. |
| + void GenerateFast(MacroAssembler* masm); |
| + |
| + // Generates the slow case code. Must not be naturally |
| + // reachable. Expected to be put after a ret instruction (e.g., in |
| + // deferred code). Always jumps back to the fast case. |
| + void GenerateSlow(MacroAssembler* masm, |
| + const RuntimeCallHelper& call_helper); |
| + |
| + private: |
| + Register object_; |
| + Register index_; |
| + Register scratch_; |
| + Register result_; |
| + |
| + Label* receiver_not_string_; |
| + Label* index_not_number_; |
| + Label* index_out_of_range_; |
| + |
| + StringIndexFlags index_flags_; |
| + |
| + Label call_runtime_; |
| + Label index_not_smi_; |
| + Label got_smi_index_; |
| + Label exit_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator); |
| +}; |
| + |
| + |
| +// Generates code for creating a one-char string from a char code. |
| +class StringCharFromCodeGenerator { |
| + public: |
| + StringCharFromCodeGenerator(Register code, |
| + Register result) |
| + : code_(code), |
| + result_(result) { |
| + ASSERT(!code_.is(result_)); |
| + } |
| + |
| + // Generates the fast case code. On the fallthrough path |result| |
| + // register contains the result. |
| + void GenerateFast(MacroAssembler* masm); |
| + |
| + // Generates the slow case code. Must not be naturally |
| + // reachable. Expected to be put after a ret instruction (e.g., in |
| + // deferred code). Always jumps back to the fast case. |
| + void GenerateSlow(MacroAssembler* masm, |
| + const RuntimeCallHelper& call_helper); |
| + |
| + private: |
| + Register code_; |
| + Register result_; |
| + |
| + Label slow_case_; |
| + Label exit_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator); |
| +}; |
| + |
| + |
| +// Generates code implementing String.prototype.charAt. |
| +// |
| +// Only supports the case when the receiver is a string and the index |
| +// is a number (smi or heap number) that is a valid index into the |
| +// string. Otherwise, bails out to the provided labels. |
| +// |
| +// Register usage: |object| may be changed to another string in a way |
| +// that doesn't affect charCodeAt/charAt semantics, |index| is |
| +// preserved, |scratch1|, |scratch2|, and |result| are clobbered. |
| +class StringCharAtGenerator { |
| + public: |
| + StringCharAtGenerator(Register object, |
| + Register index, |
| + Register scratch1, |
| + Register scratch2, |
| + Register result, |
| + Label* receiver_not_string, |
| + Label* index_not_number, |
| + Label* index_out_of_range, |
| + StringIndexFlags index_flags) |
| + : char_code_at_generator_(object, |
| + index, |
| + scratch1, |
| + scratch2, |
| + receiver_not_string, |
| + index_not_number, |
| + index_out_of_range, |
| + index_flags), |
| + char_from_code_generator_(scratch2, result) {} |
| + |
| + // Generates the fast case code. On the fallthrough path |result| |
| + // register contains the result. |
| + void GenerateFast(MacroAssembler* masm); |
| + |
| + // Generates the slow case code. Must not be naturally |
| + // reachable. Expected to be put after a ret instruction (e.g., in |
| + // deferred code). Always jumps back to the fast case. |
| + void GenerateSlow(MacroAssembler* masm, |
| + const RuntimeCallHelper& call_helper); |
| + |
| + private: |
| + StringCharCodeAtGenerator char_code_at_generator_; |
| + StringCharFromCodeGenerator char_from_code_generator_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator); |
| +}; |
| + |
| + |
| } // namespace internal |
| } // namespace v8 |