summaryrefslogtreecommitdiff
path: root/deps/v8/src/code-stubs.h
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-11-10 02:02:27 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2013-11-11 02:40:36 +0100
commitf230a1cf749e984439b5bb9729d9db9f48472827 (patch)
tree153596de2251b717ad79823f23fabf4c140d6d35 /deps/v8/src/code-stubs.h
parenta12870c823b9b67110b27a470fcac342cf1dfbd6 (diff)
downloadnode-new-f230a1cf749e984439b5bb9729d9db9f48472827.tar.gz
v8: upgrade to 3.22.24
This commit removes the simple/test-event-emitter-memory-leak test for being unreliable with the new garbage collector: the memory pressure exerted by the test case is too low for the garbage collector to kick in. It can be made to work again by limiting the heap size with the --max_old_space_size=x flag but that won't be very reliable across platforms and architectures.
Diffstat (limited to 'deps/v8/src/code-stubs.h')
-rw-r--r--deps/v8/src/code-stubs.h326
1 files changed, 188 insertions, 138 deletions
diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h
index 946eb76962..80d99d8b68 100644
--- a/deps/v8/src/code-stubs.h
+++ b/deps/v8/src/code-stubs.h
@@ -30,8 +30,9 @@
#include "allocation.h"
#include "assembler.h"
-#include "globals.h"
#include "codegen.h"
+#include "globals.h"
+#include "macro-assembler.h"
namespace v8 {
namespace internal {
@@ -200,19 +201,21 @@ class CodeStub BASE_EMBEDDED {
virtual void PrintName(StringStream* stream);
+ // Returns a name for logging/debugging purposes.
+ SmartArrayPointer<const char> GetName();
+
protected:
static bool CanUseFPRegisters();
// Generates the assembler code for the stub.
virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
+ virtual void VerifyPlatformFeatures(Isolate* isolate);
// Returns whether the code generated for this stub needs to be allocated as
// a fixed (non-moveable) code object.
virtual bool NeedsImmovableCode() { return false; }
- // Returns a name for logging/debugging purposes.
- SmartArrayPointer<const char> GetName();
virtual void PrintBaseName(StringStream* stream);
virtual void PrintState(StringStream* stream) { }
@@ -278,7 +281,7 @@ enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
struct CodeStubInterfaceDescriptor {
CodeStubInterfaceDescriptor();
int register_param_count_;
- const Register* stack_parameter_count_;
+ Register stack_parameter_count_;
// if hint_stack_parameter_count_ > 0, the code stub can optimize the
// return sequence. Default value is -1, which means it is ignored.
int hint_stack_parameter_count_;
@@ -287,7 +290,7 @@ struct CodeStubInterfaceDescriptor {
Address deoptimization_handler_;
int environment_length() const {
- if (stack_parameter_count_ != NULL) {
+ if (stack_parameter_count_.is_valid()) {
return register_param_count_ + 1;
}
return register_param_count_;
@@ -318,7 +321,7 @@ struct CodeStubInterfaceDescriptor {
// defined outside of the platform directories
#define DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index) \
((index) == (descriptor)->register_param_count_) \
- ? *((descriptor)->stack_parameter_count_) \
+ ? (descriptor)->stack_parameter_count_ \
: (descriptor)->register_params_[(index)]
@@ -402,9 +405,7 @@ enum StringAddFlags {
// Check right parameter.
STRING_ADD_CHECK_RIGHT = 1 << 1,
// Check both parameters.
- STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT,
- // Stub needs a frame before calling the runtime
- STRING_ADD_ERECT_FRAME = 1 << 2
+ STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
};
} } // namespace v8::internal
@@ -464,6 +465,27 @@ class ToNumberStub: public HydrogenCodeStub {
};
+class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
+ public:
+ NumberToStringStub() {}
+
+ virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
+
+ static void InstallDescriptors(Isolate* isolate);
+
+ // Parameters accessed via CodeStubGraphBuilder::GetParameter()
+ static const int kNumber = 0;
+
+ private:
+ virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
+ virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
+};
+
+
class FastNewClosureStub : public HydrogenCodeStub {
public:
explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
@@ -830,19 +852,12 @@ class FunctionPrototypeStub: public ICStub {
class StringLengthStub: public ICStub {
public:
- StringLengthStub(Code::Kind kind, bool support_wrapper)
- : ICStub(kind), support_wrapper_(support_wrapper) { }
+ explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { }
virtual void Generate(MacroAssembler* masm);
private:
STATIC_ASSERT(KindBits::kSize == 4);
- class WrapperModeBits: public BitField<bool, 4, 1> {};
- virtual CodeStub::Major MajorKey() { return StringLength; }
- virtual int MinorKey() {
- return KindBits::encode(kind()) | WrapperModeBits::encode(support_wrapper_);
- }
-
- bool support_wrapper_;
+ virtual CodeStub::Major MajorKey() { return StringLength; }
};
@@ -892,7 +907,7 @@ class HICStub: public HydrogenCodeStub {
class HandlerStub: public HICStub {
public:
- virtual Code::Kind GetCodeKind() const { return Code::STUB; }
+ virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
virtual int GetStubFlags() { return kind(); }
protected:
@@ -983,156 +998,177 @@ class KeyedLoadFieldStub: public LoadFieldStub {
};
-class BinaryOpStub: public PlatformCodeStub {
+class BinaryOpStub: public HydrogenCodeStub {
public:
BinaryOpStub(Token::Value op, OverwriteMode mode)
- : op_(op),
- mode_(mode),
- platform_specific_bit_(false),
- left_type_(BinaryOpIC::UNINITIALIZED),
- right_type_(BinaryOpIC::UNINITIALIZED),
- result_type_(BinaryOpIC::UNINITIALIZED),
- encoded_right_arg_(false, encode_arg_value(1)) {
+ : HydrogenCodeStub(UNINITIALIZED), op_(op), mode_(mode) {
+ ASSERT(op <= LAST_TOKEN && op >= FIRST_TOKEN);
Initialize();
- ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
}
- BinaryOpStub(
- int key,
- BinaryOpIC::TypeInfo left_type,
- BinaryOpIC::TypeInfo right_type,
- BinaryOpIC::TypeInfo result_type,
- Maybe<int32_t> fixed_right_arg)
- : op_(OpBits::decode(key)),
- mode_(ModeBits::decode(key)),
- platform_specific_bit_(PlatformSpecificBits::decode(key)),
- left_type_(left_type),
- right_type_(right_type),
- result_type_(result_type),
- encoded_right_arg_(fixed_right_arg.has_value,
- encode_arg_value(fixed_right_arg.value)) { }
+ explicit BinaryOpStub(Code::ExtraICState state)
+ : op_(decode_token(OpBits::decode(state))),
+ mode_(OverwriteModeField::decode(state)),
+ fixed_right_arg_(
+ Maybe<int>(HasFixedRightArgBits::decode(state),
+ decode_arg_value(FixedRightArgValueBits::decode(state)))),
+ left_state_(LeftStateField::decode(state)),
+ right_state_(fixed_right_arg_.has_value
+ ? ((fixed_right_arg_.value <= Smi::kMaxValue) ? SMI : INT32)
+ : RightStateField::decode(state)),
+ result_state_(ResultStateField::decode(state)) {
+ // We don't deserialize the SSE2 Field, since this is only used to be able
+ // to include SSE2 as well as non-SSE2 versions in the snapshot. For code
+ // generation we always want it to reflect the current state.
+ ASSERT(!fixed_right_arg_.has_value ||
+ can_encode_arg_value(fixed_right_arg_.value));
+ }
+
+ static const int FIRST_TOKEN = Token::BIT_OR;
+ static const int LAST_TOKEN = Token::MOD;
- static void decode_types_from_minor_key(int minor_key,
- BinaryOpIC::TypeInfo* left_type,
- BinaryOpIC::TypeInfo* right_type,
- BinaryOpIC::TypeInfo* result_type) {
- *left_type =
- static_cast<BinaryOpIC::TypeInfo>(LeftTypeBits::decode(minor_key));
- *right_type =
- static_cast<BinaryOpIC::TypeInfo>(RightTypeBits::decode(minor_key));
- *result_type =
- static_cast<BinaryOpIC::TypeInfo>(ResultTypeBits::decode(minor_key));
+ static void GenerateAheadOfTime(Isolate* isolate);
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate, CodeStubInterfaceDescriptor* descriptor);
+ static void InitializeForIsolate(Isolate* isolate) {
+ BinaryOpStub binopStub(UNINITIALIZED);
+ binopStub.InitializeInterfaceDescriptor(
+ isolate, isolate->code_stub_interface_descriptor(CodeStub::BinaryOp));
+ }
+
+ virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
+ virtual InlineCacheState GetICState() {
+ if (Max(left_state_, right_state_) == NONE) {
+ return ::v8::internal::UNINITIALIZED;
+ }
+ if (Max(left_state_, right_state_) == GENERIC) return MEGAMORPHIC;
+ return MONOMORPHIC;
}
- static Token::Value decode_op_from_minor_key(int minor_key) {
- return static_cast<Token::Value>(OpBits::decode(minor_key));
+ virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
+ ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
}
- static Maybe<int> decode_fixed_right_arg_from_minor_key(int minor_key) {
- return Maybe<int>(
- HasFixedRightArgBits::decode(minor_key),
- decode_arg_value(FixedRightArgValueBits::decode(minor_key)));
+ virtual Code::ExtraICState GetExtraICState() {
+ bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI &&
+ CpuFeatures::IsSafeForSnapshot(SSE2);
+
+ return OpBits::encode(encode_token(op_))
+ | LeftStateField::encode(left_state_)
+ | RightStateField::encode(fixed_right_arg_.has_value
+ ? NONE : right_state_)
+ | ResultStateField::encode(result_state_)
+ | HasFixedRightArgBits::encode(fixed_right_arg_.has_value)
+ | FixedRightArgValueBits::encode(fixed_right_arg_.has_value
+ ? encode_arg_value(
+ fixed_right_arg_.value)
+ : 0)
+ | SSE2Field::encode(sse_field)
+ | OverwriteModeField::encode(mode_);
}
- int fixed_right_arg_value() const {
- return decode_arg_value(encoded_right_arg_.value);
+ bool CanReuseDoubleBox() {
+ return result_state_ <= NUMBER && result_state_ > SMI &&
+ ((left_state_ > SMI && left_state_ <= NUMBER &&
+ mode_ == OVERWRITE_LEFT) ||
+ (right_state_ > SMI && right_state_ <= NUMBER &&
+ mode_ == OVERWRITE_RIGHT));
}
- static bool can_encode_arg_value(int32_t value) {
- return value > 0 &&
- IsPowerOf2(value) &&
- FixedRightArgValueBits::is_valid(WhichPowerOf2(value));
+ bool HasSideEffects(Isolate* isolate) const {
+ Handle<Type> left = GetLeftType(isolate);
+ Handle<Type> right = GetRightType(isolate);
+ return left->Maybe(Type::Receiver()) || right->Maybe(Type::Receiver());
}
- enum SmiCodeGenerateHeapNumberResults {
- ALLOW_HEAPNUMBER_RESULTS,
- NO_HEAPNUMBER_RESULTS
- };
+ virtual Handle<Code> GenerateCode(Isolate* isolate);
- private:
- Token::Value op_;
- OverwriteMode mode_;
- bool platform_specific_bit_; // Indicates SSE3 on IA32.
+ Maybe<Handle<Object> > Result(Handle<Object> left,
+ Handle<Object> right,
+ Isolate* isolate);
- // Operand type information determined at runtime.
- BinaryOpIC::TypeInfo left_type_;
- BinaryOpIC::TypeInfo right_type_;
- BinaryOpIC::TypeInfo result_type_;
+ Token::Value operation() const { return op_; }
+ OverwriteMode mode() const { return mode_; }
+ Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
- Maybe<int> encoded_right_arg_;
+ Handle<Type> GetLeftType(Isolate* isolate) const;
+ Handle<Type> GetRightType(Isolate* isolate) const;
+ Handle<Type> GetResultType(Isolate* isolate) const;
- static int encode_arg_value(int32_t value) {
- ASSERT(can_encode_arg_value(value));
- return WhichPowerOf2(value);
- }
+ void UpdateStatus(Handle<Object> left,
+ Handle<Object> right,
+ Maybe<Handle<Object> > result);
- static int32_t decode_arg_value(int value) {
- return 1 << value;
+ void PrintState(StringStream* stream);
+
+ private:
+ explicit BinaryOpStub(InitializationState state) : HydrogenCodeStub(state),
+ op_(Token::ADD),
+ mode_(NO_OVERWRITE) {
+ Initialize();
}
+ void Initialize();
- virtual void PrintName(StringStream* stream);
+ enum State { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
+
+ // We truncate the last bit of the token.
+ STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 5));
+ class LeftStateField: public BitField<State, 0, 3> {};
+ // When fixed right arg is set, we don't need to store the right state.
+ // Thus the two fields can overlap.
+ class HasFixedRightArgBits: public BitField<bool, 4, 1> {};
+ class FixedRightArgValueBits: public BitField<int, 5, 4> {};
+ class RightStateField: public BitField<State, 5, 3> {};
+ class ResultStateField: public BitField<State, 9, 3> {};
+ class SSE2Field: public BitField<bool, 12, 1> {};
+ class OverwriteModeField: public BitField<OverwriteMode, 13, 2> {};
+ class OpBits: public BitField<int, 15, 5> {};
+
+ virtual CodeStub::Major MajorKey() { return BinaryOp; }
+ virtual int NotMissMinorKey() { return GetExtraICState(); }
- // Minor key encoding in all 25 bits FFFFFHTTTRRRLLLPOOOOOOOMM.
- // Note: We actually do not need 7 bits for the operation, just 4 bits to
- // encode ADD, SUB, MUL, DIV, MOD, BIT_OR, BIT_AND, BIT_XOR, SAR, SHL, SHR.
- class ModeBits: public BitField<OverwriteMode, 0, 2> {};
- class OpBits: public BitField<Token::Value, 2, 7> {};
- class PlatformSpecificBits: public BitField<bool, 9, 1> {};
- class LeftTypeBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
- class RightTypeBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
- class ResultTypeBits: public BitField<BinaryOpIC::TypeInfo, 16, 3> {};
- class HasFixedRightArgBits: public BitField<bool, 19, 1> {};
- class FixedRightArgValueBits: public BitField<int, 20, 5> {};
-
- Major MajorKey() { return BinaryOp; }
- int MinorKey() {
- return OpBits::encode(op_)
- | ModeBits::encode(mode_)
- | PlatformSpecificBits::encode(platform_specific_bit_)
- | LeftTypeBits::encode(left_type_)
- | RightTypeBits::encode(right_type_)
- | ResultTypeBits::encode(result_type_)
- | HasFixedRightArgBits::encode(encoded_right_arg_.has_value)
- | FixedRightArgValueBits::encode(encoded_right_arg_.value);
- }
+ static Handle<Type> StateToType(State state,
+ Isolate* isolate);
+ static void Generate(Token::Value op,
+ State left,
+ int right,
+ State result,
+ OverwriteMode mode,
+ Isolate* isolate);
- // Platform-independent implementation.
- void Generate(MacroAssembler* masm);
- void GenerateCallRuntime(MacroAssembler* masm);
+ static void Generate(Token::Value op,
+ State left,
+ State right,
+ State result,
+ OverwriteMode mode,
+ Isolate* isolate);
- // Platform-independent signature, platform-specific implementation.
- void Initialize();
- void GenerateAddStrings(MacroAssembler* masm);
- void GenerateBothStringStub(MacroAssembler* masm);
- void GenerateGeneric(MacroAssembler* masm);
- void GenerateGenericStub(MacroAssembler* masm);
- void GenerateNumberStub(MacroAssembler* masm);
- void GenerateInt32Stub(MacroAssembler* masm);
- void GenerateLoadArguments(MacroAssembler* masm);
- void GenerateOddballStub(MacroAssembler* masm);
- void GenerateRegisterArgsPush(MacroAssembler* masm);
- void GenerateReturn(MacroAssembler* masm);
- void GenerateSmiStub(MacroAssembler* masm);
- void GenerateStringStub(MacroAssembler* masm);
- void GenerateTypeTransition(MacroAssembler* masm);
- void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
- void GenerateUninitializedStub(MacroAssembler* masm);
-
- // Entirely platform-specific methods are defined as static helper
- // functions in the <arch>/code-stubs-<arch>.cc files.
+ void UpdateStatus(Handle<Object> object,
+ State* state);
- virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
+ bool can_encode_arg_value(int32_t value) const;
+ int encode_arg_value(int32_t value) const;
+ int32_t decode_arg_value(int value) const;
+ int encode_token(Token::Value op) const;
+ Token::Value decode_token(int op) const;
- virtual InlineCacheState GetICState() {
- return BinaryOpIC::ToState(Max(left_type_, right_type_));
+ bool has_int_result() const {
+ return op_ == Token::BIT_XOR || op_ == Token::BIT_AND ||
+ op_ == Token::BIT_OR || op_ == Token::SAR || op_ == Token::SHL;
}
- virtual void FinishCode(Handle<Code> code) {
- code->set_stub_info(MinorKey());
- }
+ const char* StateToName(State state);
+
+ void PrintBaseName(StringStream* stream);
- friend class CodeGenerator;
+ Token::Value op_;
+ OverwriteMode mode_;
+
+ Maybe<int> fixed_right_arg_;
+ State left_state_;
+ State right_state_;
+ State result_state_;
};
@@ -1318,6 +1354,11 @@ class CEntryStub : public PlatformCodeStub {
virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
static void GenerateAheadOfTime(Isolate* isolate);
+ protected:
+ virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
+ ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
+ };
+
private:
void GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
@@ -1705,7 +1746,9 @@ class DoubleToIStub : public PlatformCodeStub {
DestinationRegisterBits::encode(destination.code_) |
OffsetBits::encode(offset) |
IsTruncatingBits::encode(is_truncating) |
- SkipFastPathBits::encode(skip_fastpath);
+ SkipFastPathBits::encode(skip_fastpath) |
+ SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
+ CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
}
Register source() {
@@ -1734,6 +1777,11 @@ class DoubleToIStub : public PlatformCodeStub {
virtual bool SometimesSetsUpAFrame() { return false; }
+ protected:
+ virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
+ ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
+ }
+
private:
static const int kBitsPerRegisterNumber = 6;
STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
@@ -1748,6 +1796,8 @@ class DoubleToIStub : public PlatformCodeStub {
public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
class SkipFastPathBits:
public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
+ class SSEBits:
+ public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT
Major MajorKey() { return DoubleToI; }
int MinorKey() { return bit_field_; }