diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 5f9d729d8d..f75ee8bde8 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -30,8 +30,7 @@ #if defined(V8_TARGET_ARCH_ARM) #include "bootstrapper.h" -#include "code-stubs-arm.h" -#include "codegen-inl.h" +#include "code-stubs.h" #include "regexp-macro-assembler.h" namespace v8 { diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h index ec30a4d316..2e07e3b5c7 100644 --- a/src/arm/code-stubs-arm.h +++ b/src/arm/code-stubs-arm.h @@ -28,9 +28,7 @@ #ifndef V8_ARM_CODE_STUBS_ARM_H_ #define V8_ARM_CODE_STUBS_ARM_H_ -#include "codegen-inl.h" #include "ic-inl.h" -#include "ast.h" namespace v8 { namespace internal { @@ -66,11 +64,13 @@ class ToBooleanStub: public CodeStub { class GenericBinaryOpStub : public CodeStub { public: + static const int kUnknownIntValue = -1; + GenericBinaryOpStub(Token::Value op, OverwriteMode mode, Register lhs, Register rhs, - int constant_rhs = CodeGenerator::kUnknownIntValue) + int constant_rhs = kUnknownIntValue) : op_(op), mode_(mode), lhs_(lhs), @@ -134,7 +134,7 @@ class GenericBinaryOpStub : public CodeStub { void GenerateTypeTransition(MacroAssembler* masm); static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) { - if (constant_rhs == CodeGenerator::kUnknownIntValue) return false; + if (constant_rhs == kUnknownIntValue) return false; if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3; if (op == Token::MOD) { if (constant_rhs <= 1) return false; @@ -470,6 +470,22 @@ class RecordWriteStub : public CodeStub { }; +// Enter C code from generated RegExp code in a way that allows +// the C code to fix the return address in case of a GC. +// Currently only needed on ARM. +class RegExpCEntryStub: public CodeStub { + public: + RegExpCEntryStub() {} + virtual ~RegExpCEntryStub() {} + void Generate(MacroAssembler* masm); + + private: + Major MajorKey() { return RegExpCEntry; } + int MinorKey() { return 0; } + const char* GetName() { return "RegExpCEntryStub"; } +}; + + } } // namespace v8::internal #endif // V8_ARM_CODE_STUBS_ARM_H_ diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 671a410733..08a8da0f73 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -30,7 +30,7 @@ #if defined(V8_TARGET_ARCH_ARM) #include "bootstrapper.h" -#include "code-stubs-arm.h" +#include "code-stubs.h" #include "codegen-inl.h" #include "compiler.h" #include "debug.h" @@ -1135,7 +1135,8 @@ void CodeGenerator::SmiOperation(Token::Value op, frame_->EmitPush(lhs, TypeInfo::Smi()); TypeInfo t = both_sides_are_smi ? TypeInfo::Smi() : TypeInfo::Unknown(); frame_->EmitPush(rhs, t); - GenericBinaryOperation(op, mode, GENERATE_INLINE_SMI, kUnknownIntValue); + GenericBinaryOperation(op, mode, GENERATE_INLINE_SMI, + GenericBinaryOpStub::kUnknownIntValue); } return; } diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h index cff4841d66..c522154ae1 100644 --- a/src/arm/codegen-arm.h +++ b/src/arm/codegen-arm.h @@ -28,8 +28,9 @@ #ifndef V8_ARM_CODEGEN_ARM_H_ #define V8_ARM_CODEGEN_ARM_H_ -#include "ic-inl.h" #include "ast.h" +#include "code-stubs-arm.h" +#include "ic-inl.h" namespace v8 { namespace internal { @@ -270,8 +271,6 @@ class CodeGenerator: public AstVisitor { void AddDeferred(DeferredCode* code) { deferred_.Add(code); } - static const int kUnknownIntValue = -1; - // If the name is an inline runtime function call return the number of // expected arguments. Otherwise return -1. static int InlineRuntimeCallArgumentsCount(Handle name); @@ -420,7 +419,8 @@ class CodeGenerator: public AstVisitor { void GenericBinaryOperation(Token::Value op, OverwriteMode overwrite_mode, GenerateInlineSmi inline_smi, - int known_rhs = kUnknownIntValue); + int known_rhs = + GenericBinaryOpStub::kUnknownIntValue); void Comparison(Condition cc, Expression* left, Expression* right, diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 694a1b672d..912fefc79f 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -29,7 +29,7 @@ #if defined(V8_TARGET_ARCH_ARM) -#include "code-stubs-arm.h" +#include "code-stubs.h" #include "codegen-inl.h" #include "compiler.h" #include "debug.h" diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc index cdf430fc36..49d7b2d03a 100644 --- a/src/arm/ic-arm.cc +++ b/src/arm/ic-arm.cc @@ -30,7 +30,7 @@ #if defined(V8_TARGET_ARCH_ARM) #include "assembler-arm.h" -#include "code-stubs-arm.h" +#include "code-stubs.h" #include "codegen-inl.h" #include "disasm.h" #include "ic-inl.h" diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc index c67c7aacaa..72b635fe03 100644 --- a/src/arm/regexp-macro-assembler-arm.cc +++ b/src/arm/regexp-macro-assembler-arm.cc @@ -31,12 +31,10 @@ #include "unicode.h" #include "log.h" -#include "ast.h" #include "code-stubs.h" #include "regexp-stack.h" #include "macro-assembler.h" #include "regexp-macro-assembler.h" -#include "arm/macro-assembler-arm.h" #include "arm/regexp-macro-assembler-arm.h" namespace v8 { diff --git a/src/arm/regexp-macro-assembler-arm.h b/src/arm/regexp-macro-assembler-arm.h index 2c0a8d84d4..93a74d7ca4 100644 --- a/src/arm/regexp-macro-assembler-arm.h +++ b/src/arm/regexp-macro-assembler-arm.h @@ -242,22 +242,6 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler { Label stack_overflow_label_; }; - -// Enter C code from generated RegExp code in a way that allows -// the C code to fix the return address in case of a GC. -// Currently only needed on ARM. -class RegExpCEntryStub: public CodeStub { - public: - RegExpCEntryStub() {} - virtual ~RegExpCEntryStub() {} - void Generate(MacroAssembler* masm); - - private: - Major MajorKey() { return RegExpCEntry; } - int MinorKey() { return 0; } - const char* GetName() { return "RegExpCEntryStub"; } -}; - #endif // V8_INTERPRETED_REGEXP diff --git a/src/code-stubs.h b/src/code-stubs.h index e5a222fcda..c2dd0a7aac 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -29,6 +29,7 @@ #define V8_CODE_STUBS_H_ #include "globals.h" +#include "macro-assembler.h" namespace v8 { namespace internal { @@ -80,6 +81,14 @@ namespace internal { CODE_STUB_LIST_ALL_PLATFORMS(V) \ CODE_STUB_LIST_ARM(V) +// Types of uncatchable exceptions. +enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION }; + +// Mode to overwrite BinaryExpression values. +enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; +enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE }; + + // Stub is base classes of all stubs. class CodeStub BASE_EMBEDDED { public: @@ -105,6 +114,12 @@ class CodeStub BASE_EMBEDDED { static int MinorKeyFromKey(uint32_t key) { return MinorKeyBits::decode(key); }; + + // Gets the major key from a code object that is a code stub or binary op IC. + static Major GetMajorKey(Code* code_stub) { + return static_cast(code_stub->major_key()); + } + static const char* MajorName(Major major_key, bool allow_unknown_keys); virtual ~CodeStub() {} @@ -172,6 +187,609 @@ class CodeStub BASE_EMBEDDED { friend class BreakPointIterator; }; + +// 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); +}; + +} } // namespace v8::internal + +#if V8_TARGET_ARCH_IA32 +#include "ia32/code-stubs-ia32.h" +#elif V8_TARGET_ARCH_X64 +#include "x64/code-stubs-x64.h" +#elif V8_TARGET_ARCH_ARM +#include "arm/code-stubs-arm.h" +#elif V8_TARGET_ARCH_MIPS +#include "mips/code-stubs-mips.h" +#else +#error Unsupported target architecture. +#endif + +namespace v8 { +namespace internal { + + +// 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 {} +}; + + +class StackCheckStub : public CodeStub { + public: + StackCheckStub() { } + + void Generate(MacroAssembler* masm); + + 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 {}; + class NegativeZeroField: public BitField {}; + class OpField: public BitField {}; + + 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 {}; + class NeverNanNanField: public BitField {}; + class IncludeNumberCompareField: public BitField {}; + class RegisterField: public BitField {}; + class ConditionField: public BitField {}; + + 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(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_; + + 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 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 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 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(in_loop_), + static_cast(flags_)); + } +#endif + + // Minor key encoding in 32 bits with Bitfield . + class InLoopBits: public BitField {}; + class FlagBits: public BitField {}; + class ArgcBits: public BitField {}; + + 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 v8::internal #endif // V8_CODE_STUBS_H_ diff --git a/src/codegen.h b/src/codegen.h index b8c9211a6a..3373d1c08e 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -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 @@ enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION }; 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 @@ class FrameRegisterState { #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 @@ class VirtualFrameRuntimeCallHelper : public RuntimeCallHelper { }; -// 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 @@ class DeferredCode: public ZoneObject { DISALLOW_COPY_AND_ASSIGN(DeferredCode); }; -class StackCheckStub : public CodeStub { - public: - StackCheckStub() { } - void Generate(MacroAssembler* masm); - - 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 {}; - class NegativeZeroField: public BitField {}; - class OpField: public BitField {}; - - 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 {}; - class NeverNanNanField: public BitField {}; - class IncludeNumberCompareField: public BitField {}; - class RegisterField: public BitField {}; - class ConditionField: public BitField {}; - - 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(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 {}; - - 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 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 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 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(in_loop_), - static_cast(flags_)); - } -#endif - - // Minor key encoding in 32 bits with Bitfield . - class InLoopBits: public BitField {}; - class FlagBits: public BitField {}; - class ArgcBits: public BitField {}; - - 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 +} } // namespace v8::internal #endif // V8_CODEGEN_H_ diff --git a/src/debug.cc b/src/debug.cc index 1234196ab6..6c1bf3e436 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -1443,7 +1443,7 @@ bool Debug::IsDebugBreak(Address addr) { // Check whether a code stub with the specified major key is a possible break // point location when looking for source break locations. bool Debug::IsSourceBreakStub(Code* code) { - CodeStub::Major major_key = code->major_key(); + CodeStub::Major major_key = CodeStub::GetMajorKey(code); return major_key == CodeStub::CallFunction; } @@ -1451,7 +1451,7 @@ bool Debug::IsSourceBreakStub(Code* code) { // Check whether a code stub with the specified major key is a possible break // location. bool Debug::IsBreakStub(Code* code) { - CodeStub::Major major_key = code->major_key(); + CodeStub::Major major_key = CodeStub::GetMajorKey(code); return major_key == CodeStub::CallFunction || major_key == CodeStub::StackCheck; } diff --git a/src/debug.h b/src/debug.h index 69a7902e6d..8b3b29e636 100644 --- a/src/debug.h +++ b/src/debug.h @@ -29,7 +29,6 @@ #define V8_DEBUG_H_ #include "assembler.h" -#include "code-stubs.h" #include "debug-agent.h" #include "execution.h" #include "factory.h" diff --git a/src/disassembler.cc b/src/disassembler.cc index 19cb6af728..e79421fe2f 100644 --- a/src/disassembler.cc +++ b/src/disassembler.cc @@ -258,11 +258,12 @@ static int DecodeIt(FILE* f, // Get the STUB key and extract major and minor key. uint32_t key = Smi::cast(obj)->value(); uint32_t minor_key = CodeStub::MinorKeyFromKey(key); - ASSERT(code->major_key() == CodeStub::MajorKeyFromKey(key)); + CodeStub::Major major_key = CodeStub::GetMajorKey(code); + ASSERT(major_key == CodeStub::MajorKeyFromKey(key)); out.AddFormatted(" %s, %s, ", Code::Kind2String(kind), - CodeStub::MajorName(code->major_key(), false)); - switch (code->major_key()) { + CodeStub::MajorName(major_key, false)); + switch (major_key) { case CodeStub::CallFunction: out.AddFormatted("argc = %d", minor_key); break; diff --git a/src/full-codegen.cc b/src/full-codegen.cc index b5baa2a9f6..59cbad95b5 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -30,6 +30,7 @@ #include "codegen-inl.h" #include "compiler.h" #include "full-codegen.h" +#include "macro-assembler.h" #include "scopes.h" #include "stub-cache.h" #include "debug.h" diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc index 11c419a55f..a095ef7bf4 100644 --- a/src/ia32/builtins-ia32.cc +++ b/src/ia32/builtins-ia32.cc @@ -29,7 +29,7 @@ #if defined(V8_TARGET_ARCH_IA32) -#include "code-stubs-ia32.h" +#include "code-stubs.h" #include "codegen-inl.h" namespace v8 { diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 39bb424208..81068866ee 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -29,9 +29,9 @@ #if defined(V8_TARGET_ARCH_IA32) +#include "code-stubs.h" #include "bootstrapper.h" -#include "code-stubs-ia32.h" -#include "codegen-inl.h" +#include "jsregexp.h" #include "regexp-macro-assembler.h" namespace v8 { @@ -149,7 +149,8 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(kPointerSize == 4); STATIC_ASSERT(kSmiTagSize == 1); STATIC_ASSERT(kSmiTag == 0); - __ mov(ecx, CodeGenerator::FixedArrayElementOperand(ecx, eax)); + __ mov(ecx, FieldOperand(ecx, eax, times_half_pointer_size, + FixedArray::kHeaderSize)); __ cmp(ecx, Factory::undefined_value()); __ j(equal, &slow_case); diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h index abd41e3260..acf4a6f948 100644 --- a/src/ia32/code-stubs-ia32.h +++ b/src/ia32/code-stubs-ia32.h @@ -28,8 +28,8 @@ #ifndef V8_IA32_CODE_STUBS_IA32_H_ #define V8_IA32_CODE_STUBS_IA32_H_ -#include "codegen-inl.h" -#include "ast.h" +#include "macro-assembler.h" +#include "code-stubs.h" #include "ic-inl.h" namespace v8 { @@ -112,11 +112,6 @@ class GenericBinaryOpStub: public CodeStub { void GenerateCall(MacroAssembler* masm, Register left, Smi* right); void GenerateCall(MacroAssembler* masm, Smi* left, Register right); - Result GenerateCall(MacroAssembler* masm, - VirtualFrame* frame, - Result* left, - Result* right); - bool ArgsInRegistersSupported() { return op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL || op_ == Token::DIV; @@ -211,6 +206,8 @@ class GenericBinaryOpStub: public CodeStub { virtual InlineCacheState GetICState() { return BinaryOpIC::ToState(runtime_operands_type_); } + + friend class CodeGenerator; }; diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index cbe64633f6..d399c35f6e 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -29,9 +29,9 @@ #if defined(V8_TARGET_ARCH_IA32) -#include "bootstrapper.h" -#include "code-stubs-ia32.h" #include "codegen-inl.h" +#include "bootstrapper.h" +#include "code-stubs.h" #include "compiler.h" #include "debug.h" #include "ic-inl.h" @@ -1451,7 +1451,7 @@ void CodeGenerator::GenericBinaryOperation(BinaryOperation* expr, overwrite_mode, NO_SMI_CODE_IN_STUB, operands_type); - answer = stub.GenerateCall(masm_, frame_, &left, &right); + answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right); } else if (right_is_smi_constant) { answer = ConstantSmiBinaryOperation(expr, &left, right.handle(), false, overwrite_mode); @@ -1474,7 +1474,7 @@ void CodeGenerator::GenericBinaryOperation(BinaryOperation* expr, overwrite_mode, NO_GENERIC_BINARY_FLAGS, operands_type); - answer = stub.GenerateCall(masm_, frame_, &left, &right); + answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right); } } @@ -1483,6 +1483,20 @@ void CodeGenerator::GenericBinaryOperation(BinaryOperation* expr, } +Result CodeGenerator::GenerateGenericBinaryOpStubCall(GenericBinaryOpStub* stub, + Result* left, + Result* right) { + if (stub->ArgsInRegistersSupported()) { + stub->SetArgsInRegisters(); + return frame_->CallStub(stub, left, right); + } else { + frame_->Push(left); + frame_->Push(right); + return frame_->CallStub(stub, 2); + } +} + + bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { Object* answer_object = Heap::undefined_value(); switch (op) { @@ -9816,21 +9830,6 @@ void Reference::SetValue(InitState init_state) { } -Result GenericBinaryOpStub::GenerateCall(MacroAssembler* masm, - VirtualFrame* frame, - Result* left, - Result* right) { - if (ArgsInRegistersSupported()) { - SetArgsInRegisters(); - return frame->CallStub(this, left, right); - } else { - frame->Push(left); - frame->Push(right); - return frame->CallStub(this, 2); - } -} - - #undef __ #define __ masm. diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index 81d091f86b..2a8d313e24 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -574,6 +574,11 @@ class CodeGenerator: public AstVisitor { void Int32BinaryOperation(BinaryOperation* node); + // Generate a stub call from the virtual frame. + Result GenerateGenericBinaryOpStubCall(GenericBinaryOpStub* stub, + Result* left, + Result* right); + void Comparison(AstNode* node, Condition cc, bool strict, diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index c457554b07..1631b04327 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -29,7 +29,7 @@ #if defined(V8_TARGET_ARCH_IA32) -#include "code-stubs-ia32.h" +#include "code-stubs.h" #include "codegen-inl.h" #include "compiler.h" #include "debug.h" diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc index a7930fb1ed..2aab7a8d94 100644 --- a/src/ia32/regexp-macro-assembler-ia32.cc +++ b/src/ia32/regexp-macro-assembler-ia32.cc @@ -31,11 +31,9 @@ #include "unicode.h" #include "log.h" -#include "ast.h" #include "regexp-stack.h" #include "macro-assembler.h" #include "regexp-macro-assembler.h" -#include "ia32/macro-assembler-ia32.h" #include "ia32/regexp-macro-assembler-ia32.h" namespace v8 { diff --git a/src/log.cc b/src/log.cc index e083f01a44..0bca5ebd86 100644 --- a/src/log.cc +++ b/src/log.cc @@ -30,6 +30,7 @@ #include "v8.h" #include "bootstrapper.h" +#include "code-stubs.h" #include "global-handles.h" #include "log.h" #include "macro-assembler.h" @@ -1266,7 +1267,8 @@ void Logger::LogCodeObject(Object* object) { case Code::BINARY_OP_IC: // fall through case Code::STUB: - description = CodeStub::MajorName(code_object->major_key(), true); + description = + CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true); if (description == NULL) description = "A stub from the snapshot"; tag = Logger::STUB_TAG; diff --git a/src/macro-assembler.h b/src/macro-assembler.h index 686a61c367..d261f57da7 100644 --- a/src/macro-assembler.h +++ b/src/macro-assembler.h @@ -83,4 +83,31 @@ const int kInvalidProtoDepth = -1; #error Unsupported target architecture. #endif +namespace v8 { +namespace internal { + +// Support for "structured" code comments. +#ifdef DEBUG + +class Comment { + public: + Comment(MacroAssembler* masm, const char* msg); + ~Comment(); + + private: + MacroAssembler* masm_; + const char* msg_; +}; + +#else + +class Comment { + public: + Comment(MacroAssembler*, const char*) {} +}; + +#endif // DEBUG + +} } // namespace v8::internal + #endif // V8_MACRO_ASSEMBLER_H_ diff --git a/src/objects-inl.h b/src/objects-inl.h index 76ab25c328..2a54062f0a 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -2321,14 +2321,13 @@ int Code::arguments_count() { } -CodeStub::Major Code::major_key() { +int Code::major_key() { ASSERT(kind() == STUB || kind() == BINARY_OP_IC); - return static_cast(READ_BYTE_FIELD(this, - kStubMajorKeyOffset)); + return READ_BYTE_FIELD(this, kStubMajorKeyOffset); } -void Code::set_major_key(CodeStub::Major major) { +void Code::set_major_key(int major) { ASSERT(kind() == STUB || kind() == BINARY_OP_IC); ASSERT(0 <= major && major < 256); WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major); diff --git a/src/objects.h b/src/objects.h index 40d56eab22..c2a3028d69 100644 --- a/src/objects.h +++ b/src/objects.h @@ -29,7 +29,6 @@ #define V8_OBJECTS_H_ #include "builtins.h" -#include "code-stubs.h" #include "smart-pointer.h" #include "unicode-inl.h" #if V8_TARGET_ARCH_ARM @@ -2886,8 +2885,8 @@ class Code: public HeapObject { inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; } // [major_key]: For kind STUB or BINARY_OP_IC, the major key. - inline CodeStub::Major major_key(); - inline void set_major_key(CodeStub::Major major); + inline int major_key(); + inline void set_major_key(int major); // Flags operations. static inline Flags ComputeFlags(Kind kind, diff --git a/src/regexp-macro-assembler.h b/src/regexp-macro-assembler.h index 9f8e2c5c81..652b690d7b 100644 --- a/src/regexp-macro-assembler.h +++ b/src/regexp-macro-assembler.h @@ -28,6 +28,8 @@ #ifndef V8_REGEXP_MACRO_ASSEMBLER_H_ #define V8_REGEXP_MACRO_ASSEMBLER_H_ +#include "ast.h" + namespace v8 { namespace internal { diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 028de50ae1..c75b9455b2 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -30,8 +30,7 @@ #if defined(V8_TARGET_ARCH_X64) #include "bootstrapper.h" -#include "code-stubs-x64.h" -#include "codegen-inl.h" +#include "code-stubs.h" #include "regexp-macro-assembler.h" namespace v8 { diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h index 149b6def15..18213b93e6 100644 --- a/src/x64/code-stubs-x64.h +++ b/src/x64/code-stubs-x64.h @@ -28,9 +28,8 @@ #ifndef V8_X64_CODE_STUBS_X64_H_ #define V8_X64_CODE_STUBS_X64_H_ -#include "codegen-inl.h" -#include "ast.h" #include "ic-inl.h" +#include "type-info.h" namespace v8 { namespace internal { @@ -107,11 +106,6 @@ class GenericBinaryOpStub: public CodeStub { void GenerateCall(MacroAssembler* masm, Register left, Smi* right); void GenerateCall(MacroAssembler* masm, Smi* left, Register right); - Result GenerateCall(MacroAssembler* masm, - VirtualFrame* frame, - Result* left, - Result* right); - bool ArgsInRegistersSupported() { return (op_ == Token::ADD) || (op_ == Token::SUB) || (op_ == Token::MUL) || (op_ == Token::DIV); @@ -202,6 +196,8 @@ class GenericBinaryOpStub: public CodeStub { virtual InlineCacheState GetICState() { return BinaryOpIC::ToState(runtime_operands_type_); } + + friend class CodeGenerator; }; class StringHelper : public AllStatic { diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 66108c3b8c..b1dd45e206 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -30,7 +30,7 @@ #if defined(V8_TARGET_ARCH_X64) #include "bootstrapper.h" -#include "code-stubs-x64.h" +#include "code-stubs.h" #include "codegen-inl.h" #include "compiler.h" #include "debug.h" @@ -1024,7 +1024,7 @@ void CodeGenerator::GenericBinaryOperation(BinaryOperation* expr, overwrite_mode, NO_SMI_CODE_IN_STUB, operands_type); - answer = stub.GenerateCall(masm_, frame_, &left, &right); + answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right); } else if (right_is_smi_constant) { answer = ConstantSmiBinaryOperation(expr, &left, right.handle(), false, overwrite_mode); @@ -1047,7 +1047,7 @@ void CodeGenerator::GenericBinaryOperation(BinaryOperation* expr, overwrite_mode, NO_GENERIC_BINARY_FLAGS, operands_type); - answer = stub.GenerateCall(masm_, frame_, &left, &right); + answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right); } } @@ -8789,17 +8789,16 @@ void Reference::SetValue(InitState init_state) { } -Result GenericBinaryOpStub::GenerateCall(MacroAssembler* masm, - VirtualFrame* frame, - Result* left, - Result* right) { - if (ArgsInRegistersSupported()) { - SetArgsInRegisters(); - return frame->CallStub(this, left, right); +Result CodeGenerator::GenerateGenericBinaryOpStubCall(GenericBinaryOpStub* stub, + Result* left, + Result* right) { + if (stub->ArgsInRegistersSupported()) { + stub->SetArgsInRegisters(); + return frame_->CallStub(stub, left, right); } else { - frame->Push(left); - frame->Push(right); - return frame->CallStub(this, 2); + frame_->Push(left); + frame_->Push(right); + return frame_->CallStub(stub, 2); } } diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 5a8b6b7e11..911ca163e7 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -492,6 +492,11 @@ class CodeGenerator: public AstVisitor { void GenericBinaryOperation(BinaryOperation* expr, OverwriteMode overwrite_mode); + // Generate a stub call from the virtual frame. + Result GenerateGenericBinaryOpStubCall(GenericBinaryOpStub* stub, + Result* left, + Result* right); + // Emits code sequence that jumps to a JumpTarget if the inputs // are both smis. Cannot be in MacroAssembler because it takes // advantage of TypeInfo to skip unneeded checks. diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 57096361cf..ccd0392a30 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -29,7 +29,7 @@ #if defined(V8_TARGET_ARCH_X64) -#include "code-stubs-x64.h" +#include "code-stubs.h" #include "codegen-inl.h" #include "compiler.h" #include "debug.h" diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc index 80318648ea..91e2b449e0 100644 --- a/src/x64/regexp-macro-assembler-x64.cc +++ b/src/x64/regexp-macro-assembler-x64.cc @@ -32,11 +32,9 @@ #include "serialize.h" #include "unicode.h" #include "log.h" -#include "ast.h" #include "regexp-stack.h" #include "macro-assembler.h" #include "regexp-macro-assembler.h" -#include "x64/macro-assembler-x64.h" #include "x64/regexp-macro-assembler-x64.h" namespace v8 { diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index ef83f28e0f..f500ce647e 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -31,10 +31,10 @@ #if defined(V8_TARGET_ARCH_X64) #include "ic-inl.h" -#include "code-stubs-x64.h" +#include "code-stubs.h" #include "codegen-inl.h" #include "stub-cache.h" -#include "macro-assembler-x64.h" +#include "macro-assembler.h" namespace v8 { namespace internal {