| Index: src/codegen.h
|
| ===================================================================
|
| --- src/codegen.h (revision 5369)
|
| +++ src/codegen.h (working copy)
|
| @@ -73,13 +73,6 @@
|
| // CodeForSourcePosition
|
|
|
|
|
| -// Mode to overwrite BinaryExpression values.
|
| -enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
|
| -enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
|
| -
|
| -// Types of uncatchable exceptions.
|
| -enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
|
| -
|
| #define INLINE_RUNTIME_FUNCTION_LIST(F) \
|
| F(IsSmi, 1, 1) \
|
| F(IsNonNegativeSmi, 1, 1) \
|
| @@ -138,29 +131,6 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -// Support for "structured" code comments.
|
| -#ifdef DEBUG
|
| -
|
| -class Comment BASE_EMBEDDED {
|
| - public:
|
| - Comment(MacroAssembler* masm, const char* msg);
|
| - ~Comment();
|
| -
|
| - private:
|
| - MacroAssembler* masm_;
|
| - const char* msg_;
|
| -};
|
| -
|
| -#else
|
| -
|
| -class Comment BASE_EMBEDDED {
|
| - public:
|
| - Comment(MacroAssembler*, const char*) {}
|
| -};
|
| -
|
| -#endif // DEBUG
|
| -
|
| -
|
| // Code generation can be nested. Code generation scopes form a stack
|
| // of active code generators.
|
| class CodeGeneratorScope BASE_EMBEDDED {
|
| @@ -233,23 +203,6 @@
|
| #endif
|
|
|
|
|
| -// 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 {
|
| @@ -267,29 +220,6 @@
|
| };
|
|
|
|
|
| -// 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.
|
| @@ -352,556 +282,7 @@
|
| DISALLOW_COPY_AND_ASSIGN(DeferredCode);
|
| };
|
|
|
| -class StackCheckStub : public CodeStub {
|
| - public:
|
| - StackCheckStub() { }
|
|
|
| - void Generate(MacroAssembler* masm);
|
| +} } // namespace v8::internal
|
|
|
| - private:
|
| -
|
| - const char* GetName() { return "StackCheckStub"; }
|
| -
|
| - Major MajorKey() { return StackCheck; }
|
| - int MinorKey() { return 0; }
|
| -};
|
| -
|
| -
|
| -class FastNewClosureStub : public CodeStub {
|
| - public:
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - const char* GetName() { return "FastNewClosureStub"; }
|
| - Major MajorKey() { return FastNewClosure; }
|
| - int MinorKey() { return 0; }
|
| -};
|
| -
|
| -
|
| -class FastNewContextStub : public CodeStub {
|
| - public:
|
| - static const int kMaximumSlots = 64;
|
| -
|
| - explicit FastNewContextStub(int slots) : slots_(slots) {
|
| - ASSERT(slots_ > 0 && slots <= kMaximumSlots);
|
| - }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - int slots_;
|
| -
|
| - const char* GetName() { return "FastNewContextStub"; }
|
| - Major MajorKey() { return FastNewContext; }
|
| - int MinorKey() { return slots_; }
|
| -};
|
| -
|
| -
|
| -class FastCloneShallowArrayStub : public CodeStub {
|
| - public:
|
| - // Maximum length of copied elements array.
|
| - static const int kMaximumClonedLength = 8;
|
| -
|
| - enum Mode {
|
| - CLONE_ELEMENTS,
|
| - COPY_ON_WRITE_ELEMENTS
|
| - };
|
| -
|
| - FastCloneShallowArrayStub(Mode mode, int length)
|
| - : mode_(mode),
|
| - length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
|
| - ASSERT(length_ >= 0);
|
| - ASSERT(length_ <= kMaximumClonedLength);
|
| - }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - Mode mode_;
|
| - int length_;
|
| -
|
| - const char* GetName() { return "FastCloneShallowArrayStub"; }
|
| - Major MajorKey() { return FastCloneShallowArray; }
|
| - int MinorKey() {
|
| - ASSERT(mode_ == 0 || mode_ == 1);
|
| - return (length_ << 1) | mode_;
|
| - }
|
| -};
|
| -
|
| -
|
| -class InstanceofStub: public CodeStub {
|
| - public:
|
| - InstanceofStub() { }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - Major MajorKey() { return Instanceof; }
|
| - int MinorKey() { return 0; }
|
| -};
|
| -
|
| -
|
| -enum NegativeZeroHandling {
|
| - kStrictNegativeZero,
|
| - kIgnoreNegativeZero
|
| -};
|
| -
|
| -
|
| -class GenericUnaryOpStub : public CodeStub {
|
| - public:
|
| - GenericUnaryOpStub(Token::Value op,
|
| - UnaryOverwriteMode overwrite,
|
| - NegativeZeroHandling negative_zero = kStrictNegativeZero)
|
| - : op_(op), overwrite_(overwrite), negative_zero_(negative_zero) { }
|
| -
|
| - private:
|
| - Token::Value op_;
|
| - UnaryOverwriteMode overwrite_;
|
| - NegativeZeroHandling negative_zero_;
|
| -
|
| - class OverwriteField: public BitField<UnaryOverwriteMode, 0, 1> {};
|
| - class NegativeZeroField: public BitField<NegativeZeroHandling, 1, 1> {};
|
| - class OpField: public BitField<Token::Value, 2, kMinorBits - 2> {};
|
| -
|
| - Major MajorKey() { return GenericUnaryOp; }
|
| - int MinorKey() {
|
| - return OpField::encode(op_) |
|
| - OverwriteField::encode(overwrite_) |
|
| - NegativeZeroField::encode(negative_zero_);
|
| - }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - const char* GetName();
|
| -};
|
| -
|
| -
|
| -enum NaNInformation {
|
| - kBothCouldBeNaN,
|
| - kCantBothBeNaN
|
| -};
|
| -
|
| -
|
| -class CompareStub: public CodeStub {
|
| - public:
|
| - CompareStub(Condition cc,
|
| - bool strict,
|
| - NaNInformation nan_info = kBothCouldBeNaN,
|
| - bool include_number_compare = true,
|
| - Register lhs = no_reg,
|
| - Register rhs = no_reg) :
|
| - cc_(cc),
|
| - strict_(strict),
|
| - never_nan_nan_(nan_info == kCantBothBeNaN),
|
| - include_number_compare_(include_number_compare),
|
| - lhs_(lhs),
|
| - rhs_(rhs),
|
| - name_(NULL) { }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - Condition cc_;
|
| - bool strict_;
|
| - // Only used for 'equal' comparisons. Tells the stub that we already know
|
| - // that at least one side of the comparison is not NaN. This allows the
|
| - // stub to use object identity in the positive case. We ignore it when
|
| - // generating the minor key for other comparisons to avoid creating more
|
| - // stubs.
|
| - bool never_nan_nan_;
|
| - // Do generate the number comparison code in the stub. Stubs without number
|
| - // comparison code is used when the number comparison has been inlined, and
|
| - // the stub will be called if one of the operands is not a number.
|
| - bool include_number_compare_;
|
| - // Register holding the left hand side of the comparison if the stub gives
|
| - // a choice, no_reg otherwise.
|
| - Register lhs_;
|
| - // Register holding the right hand side of the comparison if the stub gives
|
| - // a choice, no_reg otherwise.
|
| - Register rhs_;
|
| -
|
| - // Encoding of the minor key CCCCCCCCCCCCRCNS.
|
| - class StrictField: public BitField<bool, 0, 1> {};
|
| - class NeverNanNanField: public BitField<bool, 1, 1> {};
|
| - class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
|
| - class RegisterField: public BitField<bool, 3, 1> {};
|
| - class ConditionField: public BitField<int, 4, 12> {};
|
| -
|
| - Major MajorKey() { return Compare; }
|
| -
|
| - int MinorKey();
|
| -
|
| - // Branch to the label if the given object isn't a symbol.
|
| - void BranchIfNonSymbol(MacroAssembler* masm,
|
| - Label* label,
|
| - Register object,
|
| - Register scratch);
|
| -
|
| - // Unfortunately you have to run without snapshots to see most of these
|
| - // names in the profile since most compare stubs end up in the snapshot.
|
| - char* name_;
|
| - const char* GetName();
|
| -#ifdef DEBUG
|
| - void Print() {
|
| - PrintF("CompareStub (cc %d), (strict %s), "
|
| - "(never_nan_nan %s), (number_compare %s) ",
|
| - static_cast<int>(cc_),
|
| - strict_ ? "true" : "false",
|
| - never_nan_nan_ ? "true" : "false",
|
| - include_number_compare_ ? "included" : "not included");
|
| -
|
| - if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) {
|
| - PrintF("(lhs r%d), (rhs r%d)\n", lhs_.code(), rhs_.code());
|
| - } else {
|
| - PrintF("\n");
|
| - }
|
| - }
|
| -#endif
|
| -};
|
| -
|
| -
|
| -class CEntryStub : public CodeStub {
|
| - public:
|
| - explicit CEntryStub(int result_size) : result_size_(result_size) { }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - void GenerateCore(MacroAssembler* masm,
|
| - Label* throw_normal_exception,
|
| - Label* throw_termination_exception,
|
| - Label* throw_out_of_memory_exception,
|
| - bool do_gc,
|
| - bool always_allocate_scope,
|
| - int alignment_skew = 0);
|
| - void GenerateThrowTOS(MacroAssembler* masm);
|
| - void GenerateThrowUncatchable(MacroAssembler* masm,
|
| - UncatchableExceptionType type);
|
| -
|
| - // Number of pointers/values returned.
|
| - const int result_size_;
|
| -
|
| - // Minor key encoding
|
| - class IndirectResultBits: public BitField<bool, 1, 1> {};
|
| -
|
| - Major MajorKey() { return CEntry; }
|
| - // Minor key must differ if different result_size_ values means different
|
| - // code is generated.
|
| - int MinorKey();
|
| -
|
| - const char* GetName() { return "CEntryStub"; }
|
| -};
|
| -
|
| -
|
| -class ApiGetterEntryStub : public CodeStub {
|
| - public:
|
| - ApiGetterEntryStub(Handle<AccessorInfo> info,
|
| - ApiFunction* fun)
|
| - : info_(info),
|
| - fun_(fun) { }
|
| - void Generate(MacroAssembler* masm);
|
| - virtual bool has_custom_cache() { return true; }
|
| - virtual bool GetCustomCache(Code** code_out);
|
| - virtual void SetCustomCache(Code* value);
|
| -
|
| - static const int kStackSpace = 5;
|
| - static const int kArgc = 4;
|
| - private:
|
| - Handle<AccessorInfo> info() { return info_; }
|
| - ApiFunction* fun() { return fun_; }
|
| - Major MajorKey() { return NoCache; }
|
| - int MinorKey() { return 0; }
|
| - const char* GetName() { return "ApiEntryStub"; }
|
| - // The accessor info associated with the function.
|
| - Handle<AccessorInfo> info_;
|
| - // The function to be called.
|
| - ApiFunction* fun_;
|
| -};
|
| -
|
| -
|
| -class JSEntryStub : public CodeStub {
|
| - public:
|
| - JSEntryStub() { }
|
| -
|
| - void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
|
| -
|
| - protected:
|
| - void GenerateBody(MacroAssembler* masm, bool is_construct);
|
| -
|
| - private:
|
| - Major MajorKey() { return JSEntry; }
|
| - int MinorKey() { return 0; }
|
| -
|
| - const char* GetName() { return "JSEntryStub"; }
|
| -};
|
| -
|
| -
|
| -class JSConstructEntryStub : public JSEntryStub {
|
| - public:
|
| - JSConstructEntryStub() { }
|
| -
|
| - void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
|
| -
|
| - private:
|
| - int MinorKey() { return 1; }
|
| -
|
| - const char* GetName() { return "JSConstructEntryStub"; }
|
| -};
|
| -
|
| -
|
| -class ArgumentsAccessStub: public CodeStub {
|
| - public:
|
| - enum Type {
|
| - READ_ELEMENT,
|
| - NEW_OBJECT
|
| - };
|
| -
|
| - explicit ArgumentsAccessStub(Type type) : type_(type) { }
|
| -
|
| - private:
|
| - Type type_;
|
| -
|
| - Major MajorKey() { return ArgumentsAccess; }
|
| - int MinorKey() { return type_; }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| - void GenerateReadElement(MacroAssembler* masm);
|
| - void GenerateNewObject(MacroAssembler* masm);
|
| -
|
| - const char* GetName() { return "ArgumentsAccessStub"; }
|
| -
|
| -#ifdef DEBUG
|
| - void Print() {
|
| - PrintF("ArgumentsAccessStub (type %d)\n", type_);
|
| - }
|
| -#endif
|
| -};
|
| -
|
| -
|
| -class RegExpExecStub: public CodeStub {
|
| - public:
|
| - RegExpExecStub() { }
|
| -
|
| - private:
|
| - Major MajorKey() { return RegExpExec; }
|
| - int MinorKey() { return 0; }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - const char* GetName() { return "RegExpExecStub"; }
|
| -
|
| -#ifdef DEBUG
|
| - void Print() {
|
| - PrintF("RegExpExecStub\n");
|
| - }
|
| -#endif
|
| -};
|
| -
|
| -
|
| -class CallFunctionStub: public CodeStub {
|
| - public:
|
| - CallFunctionStub(int argc, InLoopFlag in_loop, CallFunctionFlags flags)
|
| - : argc_(argc), in_loop_(in_loop), flags_(flags) { }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - int argc_;
|
| - InLoopFlag in_loop_;
|
| - CallFunctionFlags flags_;
|
| -
|
| -#ifdef DEBUG
|
| - void Print() {
|
| - PrintF("CallFunctionStub (args %d, in_loop %d, flags %d)\n",
|
| - argc_,
|
| - static_cast<int>(in_loop_),
|
| - static_cast<int>(flags_));
|
| - }
|
| -#endif
|
| -
|
| - // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
|
| - class InLoopBits: public BitField<InLoopFlag, 0, 1> {};
|
| - class FlagBits: public BitField<CallFunctionFlags, 1, 1> {};
|
| - class ArgcBits: public BitField<int, 2, 32 - 2> {};
|
| -
|
| - Major MajorKey() { return CallFunction; }
|
| - int MinorKey() {
|
| - // Encode the parameters in a unique 32 bit value.
|
| - return InLoopBits::encode(in_loop_)
|
| - | FlagBits::encode(flags_)
|
| - | ArgcBits::encode(argc_);
|
| - }
|
| -
|
| - InLoopFlag InLoop() { return in_loop_; }
|
| - bool ReceiverMightBeValue() {
|
| - return (flags_ & RECEIVER_MIGHT_BE_VALUE) != 0;
|
| - }
|
| -
|
| - public:
|
| - static int ExtractArgcFromMinorKey(int minor_key) {
|
| - return ArgcBits::decode(minor_key);
|
| - }
|
| -};
|
| -
|
| -
|
| -enum StringIndexFlags {
|
| - // Accepts smis or heap numbers.
|
| - STRING_INDEX_IS_NUMBER,
|
| -
|
| - // Accepts smis or heap numbers that are valid array indices
|
| - // (ECMA-262 15.4). Invalid indices are reported as being out of
|
| - // range.
|
| - STRING_INDEX_IS_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. Additional index constraints are specified by the
|
| -// flags. 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. Additional index constraints are specified by the
|
| -// flags. 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
|
| -
|
| #endif // V8_CODEGEN_H_
|
|
|