2012-02-10 08:47:35 +00:00
|
|
|
// Copyright 2012 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
#ifndef V8_CODE_STUBS_H_
|
|
|
|
#define V8_CODE_STUBS_H_
|
|
|
|
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/allocation.h"
|
|
|
|
#include "src/assembler.h"
|
|
|
|
#include "src/codegen.h"
|
|
|
|
#include "src/globals.h"
|
|
|
|
#include "src/macro-assembler.h"
|
2014-07-30 13:54:45 +00:00
|
|
|
#include "src/ostreams.h"
|
2010-03-01 16:24:05 +00:00
|
|
|
|
2009-05-25 10:05:56 +00:00
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2011-05-25 12:26:15 +00:00
|
|
|
// List of code stubs used on all platforms.
|
2014-07-23 11:16:29 +00:00
|
|
|
#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
|
|
|
|
V(CallFunction) \
|
|
|
|
V(CallConstruct) \
|
|
|
|
V(BinaryOpIC) \
|
|
|
|
V(BinaryOpICWithAllocationSite) \
|
|
|
|
V(BinaryOpWithAllocationSite) \
|
|
|
|
V(StringAdd) \
|
|
|
|
V(SubString) \
|
|
|
|
V(StringCompare) \
|
|
|
|
V(Compare) \
|
|
|
|
V(CompareIC) \
|
|
|
|
V(CompareNilIC) \
|
|
|
|
V(MathPow) \
|
|
|
|
V(CallIC) \
|
|
|
|
V(CallIC_Array) \
|
|
|
|
V(FunctionPrototype) \
|
|
|
|
V(RecordWrite) \
|
|
|
|
V(StoreBufferOverflow) \
|
|
|
|
V(RegExpExec) \
|
|
|
|
V(Instanceof) \
|
|
|
|
V(ConvertToDouble) \
|
|
|
|
V(WriteInt32ToHeapNumber) \
|
|
|
|
V(StackCheck) \
|
|
|
|
V(Interrupt) \
|
|
|
|
V(FastNewClosure) \
|
|
|
|
V(FastNewContext) \
|
|
|
|
V(FastCloneShallowArray) \
|
|
|
|
V(FastCloneShallowObject) \
|
|
|
|
V(CreateAllocationSite) \
|
|
|
|
V(ToBoolean) \
|
|
|
|
V(ToNumber) \
|
|
|
|
V(ArgumentsAccess) \
|
|
|
|
V(RegExpConstructResult) \
|
|
|
|
V(NumberToString) \
|
|
|
|
V(DoubleToI) \
|
|
|
|
V(CEntry) \
|
|
|
|
V(JSEntry) \
|
2014-07-29 16:07:34 +00:00
|
|
|
V(LoadElement) \
|
2014-07-23 11:16:29 +00:00
|
|
|
V(KeyedLoadGeneric) \
|
|
|
|
V(ArrayNoArgumentConstructor) \
|
|
|
|
V(ArraySingleArgumentConstructor) \
|
|
|
|
V(ArrayNArgumentsConstructor) \
|
|
|
|
V(InternalArrayNoArgumentConstructor) \
|
|
|
|
V(InternalArraySingleArgumentConstructor) \
|
|
|
|
V(InternalArrayNArgumentsConstructor) \
|
2014-07-29 16:07:34 +00:00
|
|
|
V(StoreElement) \
|
2014-07-23 11:16:29 +00:00
|
|
|
V(DebuggerStatement) \
|
|
|
|
V(NameDictionaryLookup) \
|
|
|
|
V(ElementsTransitionAndStore) \
|
|
|
|
V(TransitionElementsKind) \
|
|
|
|
V(StoreArrayLiteralElement) \
|
|
|
|
V(StubFailureTrampoline) \
|
|
|
|
V(ArrayConstructor) \
|
|
|
|
V(InternalArrayConstructor) \
|
|
|
|
V(ProfileEntryHook) \
|
|
|
|
V(StoreGlobal) \
|
|
|
|
V(CallApiFunction) \
|
|
|
|
V(CallApiGetter) \
|
|
|
|
/* IC Handler stubs */ \
|
|
|
|
V(LoadField) \
|
|
|
|
V(StringLength)
|
2009-10-26 12:26:42 +00:00
|
|
|
|
2014-03-24 16:41:37 +00:00
|
|
|
// List of code stubs only used on ARM 32 bits platforms.
|
|
|
|
#if V8_TARGET_ARCH_ARM
|
2009-10-26 12:26:42 +00:00
|
|
|
#define CODE_STUB_LIST_ARM(V) \
|
|
|
|
V(GetProperty) \
|
|
|
|
V(SetProperty) \
|
|
|
|
V(InvokeBuiltin) \
|
2011-02-04 13:43:38 +00:00
|
|
|
V(DirectCEntry)
|
2009-10-26 12:26:42 +00:00
|
|
|
#else
|
|
|
|
#define CODE_STUB_LIST_ARM(V)
|
|
|
|
#endif
|
|
|
|
|
2014-03-24 16:41:37 +00:00
|
|
|
// List of code stubs only used on ARM 64 bits platforms.
|
|
|
|
#if V8_TARGET_ARCH_ARM64
|
|
|
|
#define CODE_STUB_LIST_ARM64(V) \
|
|
|
|
V(GetProperty) \
|
|
|
|
V(SetProperty) \
|
|
|
|
V(InvokeBuiltin) \
|
|
|
|
V(DirectCEntry) \
|
|
|
|
V(StoreRegistersState) \
|
|
|
|
V(RestoreRegistersState)
|
|
|
|
#else
|
|
|
|
#define CODE_STUB_LIST_ARM64(V)
|
|
|
|
#endif
|
|
|
|
|
2011-03-28 13:05:36 +00:00
|
|
|
// List of code stubs only used on MIPS platforms.
|
2013-06-28 15:34:48 +00:00
|
|
|
#if V8_TARGET_ARCH_MIPS
|
2014-07-09 11:08:26 +00:00
|
|
|
#define CODE_STUB_LIST_MIPS(V) \
|
|
|
|
V(RegExpCEntry) \
|
|
|
|
V(DirectCEntry) \
|
|
|
|
V(StoreRegistersState) \
|
|
|
|
V(RestoreRegistersState)
|
|
|
|
#elif V8_TARGET_ARCH_MIPS64
|
2011-03-28 13:05:36 +00:00
|
|
|
#define CODE_STUB_LIST_MIPS(V) \
|
2011-05-16 08:38:19 +00:00
|
|
|
V(RegExpCEntry) \
|
2013-12-20 19:44:03 +00:00
|
|
|
V(DirectCEntry) \
|
|
|
|
V(StoreRegistersState) \
|
|
|
|
V(RestoreRegistersState)
|
2011-03-28 13:05:36 +00:00
|
|
|
#else
|
|
|
|
#define CODE_STUB_LIST_MIPS(V)
|
|
|
|
#endif
|
|
|
|
|
2009-10-26 12:26:42 +00:00
|
|
|
// Combined list of code stubs.
|
2009-11-11 14:32:14 +00:00
|
|
|
#define CODE_STUB_LIST(V) \
|
|
|
|
CODE_STUB_LIST_ALL_PLATFORMS(V) \
|
2011-03-28 13:05:36 +00:00
|
|
|
CODE_STUB_LIST_ARM(V) \
|
2014-03-24 16:41:37 +00:00
|
|
|
CODE_STUB_LIST_ARM64(V) \
|
2011-03-28 13:05:36 +00:00
|
|
|
CODE_STUB_LIST_MIPS(V)
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Stub is base classes of all stubs.
|
|
|
|
class CodeStub BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
enum Major {
|
2013-12-13 10:27:19 +00:00
|
|
|
UninitializedMajorKey = 0,
|
2009-10-26 12:26:42 +00:00
|
|
|
#define DEF_ENUM(name) name,
|
|
|
|
CODE_STUB_LIST(DEF_ENUM)
|
|
|
|
#undef DEF_ENUM
|
2009-11-04 08:51:48 +00:00
|
|
|
NoCache, // marker for stubs that do custom caching
|
2008-07-03 15:10:15 +00:00
|
|
|
NUMBER_OF_IDS
|
|
|
|
};
|
|
|
|
|
|
|
|
// Retrieve the code for the stub. Generate the code if needed.
|
2014-04-24 12:07:40 +00:00
|
|
|
Handle<Code> GetCode();
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2013-07-05 10:34:02 +00:00
|
|
|
// Retrieve the code for the stub, make and return a copy of the code.
|
2014-04-24 12:07:40 +00:00
|
|
|
Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
|
2014-03-18 14:15:09 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
static Major MajorKeyFromKey(uint32_t key) {
|
|
|
|
return static_cast<Major>(MajorKeyBits::decode(key));
|
2010-09-02 10:18:44 +00:00
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
static int MinorKeyFromKey(uint32_t key) {
|
|
|
|
return MinorKeyBits::decode(key);
|
2010-09-02 10:18:44 +00:00
|
|
|
}
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
// Gets the major key from a code object that is a code stub or binary op IC.
|
|
|
|
static Major GetMajorKey(Code* code_stub) {
|
2014-07-21 13:10:14 +00:00
|
|
|
return MajorKeyFromKey(code_stub->stub_key());
|
2010-08-30 11:48:07 +00:00
|
|
|
}
|
|
|
|
|
2014-07-21 13:10:14 +00:00
|
|
|
static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
|
|
|
|
|
2010-02-05 13:07:00 +00:00
|
|
|
static const char* MajorName(Major major_key, bool allow_unknown_keys);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit CodeStub(Isolate* isolate) : isolate_(isolate) { }
|
2008-07-03 15:10:15 +00:00
|
|
|
virtual ~CodeStub() {}
|
|
|
|
|
2013-02-27 12:33:24 +00:00
|
|
|
static void GenerateStubsAheadOfTime(Isolate* isolate);
|
|
|
|
static void GenerateFPStubs(Isolate* isolate);
|
2011-09-16 11:29:13 +00:00
|
|
|
|
2011-09-15 11:30:45 +00:00
|
|
|
// Some stubs put untagged junk on the stack that cannot be scanned by the
|
|
|
|
// GC. This means that we must be statically sure that no GC can occur while
|
|
|
|
// they are running. If that is the case they should override this to return
|
|
|
|
// true, which will cause an assertion if we try to call something that can
|
|
|
|
// GC or if we try to put a stack frame on top of the junk, which would not
|
|
|
|
// result in a traversable stack.
|
|
|
|
virtual bool SometimesSetsUpAFrame() { return true; }
|
|
|
|
|
2011-11-09 15:44:13 +00:00
|
|
|
// Lookup the code in the (possibly custom) cache.
|
2014-04-24 12:07:40 +00:00
|
|
|
bool FindCodeInCache(Code** code_out);
|
2011-11-09 15:44:13 +00:00
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
// Returns information for computing the number key.
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const = 0;
|
|
|
|
virtual int MinorKey() const = 0;
|
2012-12-18 16:25:45 +00:00
|
|
|
|
|
|
|
virtual InlineCacheState GetICState() {
|
|
|
|
return UNINITIALIZED;
|
|
|
|
}
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
|
2013-05-02 16:32:47 +00:00
|
|
|
virtual Code::StubType GetStubType() {
|
|
|
|
return Code::NORMAL;
|
|
|
|
}
|
2013-04-18 09:50:46 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
friend OStream& operator<<(OStream& os, const CodeStub& s) {
|
|
|
|
s.PrintName(os);
|
|
|
|
return os;
|
|
|
|
}
|
2013-10-02 11:27:37 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
Isolate* isolate() const { return isolate_; }
|
|
|
|
|
2013-04-18 09:50:46 +00:00
|
|
|
protected:
|
|
|
|
// Generates the assembler code for the stub.
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() = 0;
|
2013-04-18 09:50:46 +00:00
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
// Returns whether the code generated for this stub needs to be allocated as
|
|
|
|
// a fixed (non-moveable) code object.
|
|
|
|
virtual bool NeedsImmovableCode() { return false; }
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const; // NOLINT
|
|
|
|
virtual void PrintBaseName(OStream& os) const; // NOLINT
|
|
|
|
virtual void PrintState(OStream& os) const { ; } // NOLINT
|
2013-07-05 09:26:22 +00:00
|
|
|
|
2014-07-21 13:10:14 +00:00
|
|
|
// Computes the key based on major and minor.
|
|
|
|
uint32_t GetKey() {
|
|
|
|
ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
|
|
|
|
return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
|
|
|
|
}
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
private:
|
2009-12-09 14:54:34 +00:00
|
|
|
// Perform bookkeeping required after code generation when stub code is
|
|
|
|
// initially generated.
|
2014-04-24 12:07:40 +00:00
|
|
|
void RecordCodeGeneration(Handle<Code> code);
|
2009-12-09 14:54:34 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
// Finish the code object after it has been generated.
|
2011-11-11 13:48:14 +00:00
|
|
|
virtual void FinishCode(Handle<Code> code) { }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
// Activate newly generated stub. Is called after
|
|
|
|
// registering stub in the stub cache.
|
|
|
|
virtual void Activate(Code* code) { }
|
|
|
|
|
2011-05-24 12:20:16 +00:00
|
|
|
// BinaryOpStub needs to override this.
|
2013-04-18 09:50:46 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const;
|
2010-03-01 16:24:05 +00:00
|
|
|
|
2011-12-09 09:26:14 +00:00
|
|
|
// Add the code to a specialized cache, specific to an individual
|
|
|
|
// stub type. Please note, this method must add the code object to a
|
|
|
|
// roots object, otherwise we will remove the code during GC.
|
|
|
|
virtual void AddToSpecialCache(Handle<Code> new_object) { }
|
|
|
|
|
|
|
|
// Find code in a specialized cache, work is delegated to the specific stub.
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual bool FindCodeInSpecialCache(Code** code_out) {
|
2012-11-22 07:58:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-12-09 09:26:14 +00:00
|
|
|
|
|
|
|
// If a stub uses a special cache override this.
|
|
|
|
virtual bool UseSpecialCache() { return false; }
|
|
|
|
|
2013-12-10 09:44:44 +00:00
|
|
|
STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
|
2012-07-06 22:08:27 +00:00
|
|
|
class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
|
|
|
|
class MinorKeyBits: public BitField<uint32_t,
|
|
|
|
kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
friend class BreakPointIterator;
|
2014-04-24 06:25:42 +00:00
|
|
|
|
|
|
|
Isolate* isolate_;
|
2008-07-03 15:10:15 +00:00
|
|
|
};
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class PlatformCodeStub : public CodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) { }
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
// Retrieve the code for the stub. Generate the code if needed.
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2012-12-18 16:25:45 +00:00
|
|
|
|
2013-04-18 09:50:46 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::STUB; }
|
2012-12-18 16:25:45 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// Generates the assembler code for the stub.
|
|
|
|
virtual void Generate(MacroAssembler* masm) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-04-02 11:28:01 +00:00
|
|
|
enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
|
2013-11-13 10:07:04 +00:00
|
|
|
enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-07-17 11:50:04 +00:00
|
|
|
|
|
|
|
class PlatformInterfaceDescriptor;
|
|
|
|
|
|
|
|
|
|
|
|
class InterfaceDescriptor {
|
|
|
|
public:
|
|
|
|
bool IsInitialized() const { return register_param_count_ >= 0; }
|
|
|
|
|
|
|
|
int GetEnvironmentLength() const { return register_param_count_; }
|
|
|
|
|
|
|
|
int GetRegisterParameterCount() const { return register_param_count_; }
|
|
|
|
|
|
|
|
Register GetParameterRegister(int index) const {
|
|
|
|
return register_params_[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
Representation GetParameterRepresentation(int index) const {
|
|
|
|
ASSERT(index < register_param_count_);
|
|
|
|
if (register_param_representations_.get() == NULL) {
|
|
|
|
return Representation::Tagged();
|
|
|
|
}
|
|
|
|
|
|
|
|
return register_param_representations_[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
// "Environment" versions of parameter functions. The first register
|
|
|
|
// parameter (context) is not included.
|
|
|
|
int GetEnvironmentParameterCount() const {
|
|
|
|
return GetEnvironmentLength() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Register GetEnvironmentParameterRegister(int index) const {
|
|
|
|
return GetParameterRegister(index + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Representation GetEnvironmentParameterRepresentation(int index) const {
|
|
|
|
return GetParameterRepresentation(index + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some platforms have extra information to associate with the descriptor.
|
|
|
|
PlatformInterfaceDescriptor* platform_specific_descriptor() const {
|
|
|
|
return platform_specific_descriptor_;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const Register ContextRegister();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
InterfaceDescriptor();
|
|
|
|
virtual ~InterfaceDescriptor() {}
|
|
|
|
|
|
|
|
void Initialize(int register_parameter_count, Register* registers,
|
|
|
|
Representation* register_param_representations,
|
|
|
|
PlatformInterfaceDescriptor* platform_descriptor = NULL);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int register_param_count_;
|
|
|
|
|
|
|
|
// The Register params are allocated dynamically by the
|
|
|
|
// InterfaceDescriptor, and freed on destruction. This is because static
|
|
|
|
// arrays of Registers cause creation of runtime static initializers
|
|
|
|
// which we don't want.
|
|
|
|
SmartArrayPointer<Register> register_params_;
|
|
|
|
// Specifies Representations for the stub's parameter. Points to an array of
|
|
|
|
// Representations of the same length of the numbers of parameters to the
|
|
|
|
// stub, or if NULL (the default value), Representation of each parameter
|
|
|
|
// assumed to be Tagged().
|
|
|
|
SmartArrayPointer<Representation> register_param_representations_;
|
|
|
|
|
|
|
|
PlatformInterfaceDescriptor* platform_specific_descriptor_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InterfaceDescriptor);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CodeStubInterfaceDescriptor: public InterfaceDescriptor {
|
2014-06-25 12:32:12 +00:00
|
|
|
public:
|
2013-04-18 20:37:27 +00:00
|
|
|
CodeStubInterfaceDescriptor();
|
2013-03-08 21:07:55 +00:00
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
void Initialize(CodeStub::Major major, int register_parameter_count,
|
|
|
|
Register* registers, Address deoptimization_handler = NULL,
|
2014-06-25 12:32:12 +00:00
|
|
|
Representation* register_param_representations = NULL,
|
|
|
|
int hint_stack_parameter_count = -1,
|
|
|
|
StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
|
2014-07-30 13:54:45 +00:00
|
|
|
void Initialize(CodeStub::Major major, int register_parameter_count,
|
|
|
|
Register* registers, Register stack_parameter_count,
|
2014-06-25 12:32:12 +00:00
|
|
|
Address deoptimization_handler = NULL,
|
|
|
|
Representation* register_param_representations = NULL,
|
|
|
|
int hint_stack_parameter_count = -1,
|
|
|
|
StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
|
|
|
|
HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
|
2013-04-25 16:00:32 +00:00
|
|
|
|
2013-05-24 11:44:55 +00:00
|
|
|
void SetMissHandler(ExternalReference handler) {
|
|
|
|
miss_handler_ = handler;
|
|
|
|
has_miss_handler_ = true;
|
2013-11-13 10:07:04 +00:00
|
|
|
// Our miss handler infrastructure doesn't currently support
|
|
|
|
// variable stack parameter counts.
|
|
|
|
ASSERT(!stack_parameter_count_.is_valid());
|
2013-05-24 11:44:55 +00:00
|
|
|
}
|
|
|
|
|
2014-06-25 12:32:12 +00:00
|
|
|
ExternalReference miss_handler() const {
|
2013-05-24 11:44:55 +00:00
|
|
|
ASSERT(has_miss_handler_);
|
|
|
|
return miss_handler_;
|
|
|
|
}
|
|
|
|
|
2014-06-25 12:32:12 +00:00
|
|
|
bool has_miss_handler() const {
|
2013-05-24 11:44:55 +00:00
|
|
|
return has_miss_handler_;
|
|
|
|
}
|
|
|
|
|
2014-07-17 11:50:04 +00:00
|
|
|
bool IsEnvironmentParameterCountRegister(int index) const {
|
|
|
|
return GetEnvironmentParameterRegister(index).is(stack_parameter_count_);
|
2013-11-13 10:07:04 +00:00
|
|
|
}
|
|
|
|
|
2014-06-25 12:32:12 +00:00
|
|
|
int GetHandlerParameterCount() const {
|
2014-07-17 11:50:04 +00:00
|
|
|
int params = GetEnvironmentParameterCount();
|
2013-11-13 10:07:04 +00:00
|
|
|
if (handler_arguments_mode_ == PASS_ARGUMENTS) {
|
|
|
|
params += 1;
|
|
|
|
}
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
2014-06-25 12:32:12 +00:00
|
|
|
int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
|
|
|
|
Register stack_parameter_count() const { return stack_parameter_count_; }
|
|
|
|
StubFunctionMode function_mode() const { return function_mode_; }
|
|
|
|
Address deoptimization_handler() const { return deoptimization_handler_; }
|
2014-07-30 13:54:45 +00:00
|
|
|
CodeStub::Major MajorKey() const { return major_; }
|
2014-06-25 12:32:12 +00:00
|
|
|
|
2013-05-24 11:44:55 +00:00
|
|
|
private:
|
2014-06-25 12:32:12 +00:00
|
|
|
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_;
|
|
|
|
StubFunctionMode function_mode_;
|
|
|
|
|
|
|
|
Address deoptimization_handler_;
|
|
|
|
HandlerArgumentsMode handler_arguments_mode_;
|
|
|
|
|
2013-05-24 11:44:55 +00:00
|
|
|
ExternalReference miss_handler_;
|
|
|
|
bool has_miss_handler_;
|
2014-07-30 13:54:45 +00:00
|
|
|
CodeStub::Major major_;
|
2012-12-18 16:25:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-17 11:50:04 +00:00
|
|
|
class CallInterfaceDescriptor: public InterfaceDescriptor {
|
2014-06-25 12:52:58 +00:00
|
|
|
public:
|
2014-07-17 11:50:04 +00:00
|
|
|
CallInterfaceDescriptor() { }
|
This is a preview of a first step towards unification of the hydrogen
call machinery. The change replaces CallNamed, CallKeyed,
CallConstantFunction and CallKnownGlobal hydrogen instructions with two
new instructions with a more lower level semantics:
1. CallJSFunction for direct calls of JSFunction objects (no
argument adaptation)
2. CallWithDescriptor for calls of a given Code object according to
the supplied calling convention.
Details:
CallJSFunction should be straightforward, the main difference from the
existing InvokeFunction instruction is the absence of argument adaptor
handling. (As a next step, we will replace InvokeFunction with an
equivalent hydrogen code.)
For CallWithDescriptor, the calling conventions are represented by a
tweaked version of CallStubInterfaceDescriptor. In addition to the
parameter-register mapping, we also define parameter-representation
mapping there. The CallWithDescriptor instruction has variable number of
parameters now - this required some simple tweaks in Lithium, which
assumed fixed number of arguments in some places.
The calling conventions used in the calls are initialized in the
CallDescriptors class (code-stubs.h, <arch>/code-stubs-<arch>.cc), and
they live in a new table in the Isolate class. I should say I am not
quite sure about Representation::Integer32() representation for some of
the params of ArgumentAdaptorCall - it is not clear to me wether the
params could not end up on the stack and thus confuse the GC.
The change also includes an earlier small change to argument adaptor
(https://codereview.chromium.org/98463007) that avoids passing a naked
pointer to the code entry as a parameter. I am sorry for packaging that
with an already biggish change.
Performance implications:
Locally, I see a small regression (.2% or so). It is hard to say where
exactly it comes from, but I do see inefficient call sequences to the
adaptor trampoline. For example:
;;; <@78,#24> constant-t
bf85aa515a mov edi,0x5a51aa85 ;; debug: position 29
;;; <@72,#53> load-named-field
8b7717 mov esi,[edi+0x17] ;; debug: position 195
;;; <@80,#51> constant-s
b902000000 mov ecx,0x2 ;; debug: position 195
;;; <@81,#51> gap
894df0 mov [ebp+0xf0],ecx
;;; <@82,#103> constant-i
bb01000000 mov ebx,0x1
;;; <@84,#102> constant-i
b902000000 mov ecx,0x2
;;; <@85,#102> gap
89d8 mov eax,ebx
89cb mov ebx,ecx
8b4df0 mov ecx,[ebp+0xf0]
;;; <@86,#58> call-with-descriptor
e8ef57fcff call ArgumentsAdaptorTrampoline (0x2d80e6e0) ;; code: BUILTIN
Note the silly handling of ecx; the hydrogen for this code is:
0 4 s27 Constant 1 range:1_1 <|@
0 3 t30 Constant 0x5bc1aa85 <JS Function xyz (SharedFunctionInfo 0x5bc1a919)> type:object <|@
0 1 t36 LoadNamedField t30.[in-object]@24 <|@
0 1 t38 Constant 0x2300e6a1 <Code> <|@
0 1 i102 Constant 2 range:2_2 <|@
0 1 i103 Constant 1 range:1_1 <|@
0 2 t41 CallWithDescriptor t38 t30 t36 s27 i103 i102 #2 changes[*] <|@
BUG=
R=verwaest@chromium.org, danno@chromium.org
Review URL: https://codereview.chromium.org/104663004
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18626 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-15 17:00:35 +00:00
|
|
|
|
2014-06-25 12:52:58 +00:00
|
|
|
// A copy of the passed in registers and param_representations is made
|
|
|
|
// and owned by the CallInterfaceDescriptor.
|
|
|
|
|
|
|
|
// TODO(mvstanton): Instead of taking parallel arrays register and
|
|
|
|
// param_representations, how about a struct that puts the representation
|
|
|
|
// and register side by side (eg, RegRep(r1, Representation::Tagged()).
|
|
|
|
// The same should go for the CodeStubInterfaceDescriptor class.
|
|
|
|
void Initialize(int register_parameter_count, Register* registers,
|
|
|
|
Representation* param_representations,
|
2014-07-17 11:50:04 +00:00
|
|
|
PlatformInterfaceDescriptor* platform_descriptor = NULL);
|
This is a preview of a first step towards unification of the hydrogen
call machinery. The change replaces CallNamed, CallKeyed,
CallConstantFunction and CallKnownGlobal hydrogen instructions with two
new instructions with a more lower level semantics:
1. CallJSFunction for direct calls of JSFunction objects (no
argument adaptation)
2. CallWithDescriptor for calls of a given Code object according to
the supplied calling convention.
Details:
CallJSFunction should be straightforward, the main difference from the
existing InvokeFunction instruction is the absence of argument adaptor
handling. (As a next step, we will replace InvokeFunction with an
equivalent hydrogen code.)
For CallWithDescriptor, the calling conventions are represented by a
tweaked version of CallStubInterfaceDescriptor. In addition to the
parameter-register mapping, we also define parameter-representation
mapping there. The CallWithDescriptor instruction has variable number of
parameters now - this required some simple tweaks in Lithium, which
assumed fixed number of arguments in some places.
The calling conventions used in the calls are initialized in the
CallDescriptors class (code-stubs.h, <arch>/code-stubs-<arch>.cc), and
they live in a new table in the Isolate class. I should say I am not
quite sure about Representation::Integer32() representation for some of
the params of ArgumentAdaptorCall - it is not clear to me wether the
params could not end up on the stack and thus confuse the GC.
The change also includes an earlier small change to argument adaptor
(https://codereview.chromium.org/98463007) that avoids passing a naked
pointer to the code entry as a parameter. I am sorry for packaging that
with an already biggish change.
Performance implications:
Locally, I see a small regression (.2% or so). It is hard to say where
exactly it comes from, but I do see inefficient call sequences to the
adaptor trampoline. For example:
;;; <@78,#24> constant-t
bf85aa515a mov edi,0x5a51aa85 ;; debug: position 29
;;; <@72,#53> load-named-field
8b7717 mov esi,[edi+0x17] ;; debug: position 195
;;; <@80,#51> constant-s
b902000000 mov ecx,0x2 ;; debug: position 195
;;; <@81,#51> gap
894df0 mov [ebp+0xf0],ecx
;;; <@82,#103> constant-i
bb01000000 mov ebx,0x1
;;; <@84,#102> constant-i
b902000000 mov ecx,0x2
;;; <@85,#102> gap
89d8 mov eax,ebx
89cb mov ebx,ecx
8b4df0 mov ecx,[ebp+0xf0]
;;; <@86,#58> call-with-descriptor
e8ef57fcff call ArgumentsAdaptorTrampoline (0x2d80e6e0) ;; code: BUILTIN
Note the silly handling of ecx; the hydrogen for this code is:
0 4 s27 Constant 1 range:1_1 <|@
0 3 t30 Constant 0x5bc1aa85 <JS Function xyz (SharedFunctionInfo 0x5bc1a919)> type:object <|@
0 1 t36 LoadNamedField t30.[in-object]@24 <|@
0 1 t38 Constant 0x2300e6a1 <Code> <|@
0 1 i102 Constant 2 range:2_2 <|@
0 1 i103 Constant 1 range:1_1 <|@
0 2 t41 CallWithDescriptor t38 t30 t36 s27 i103 i102 #2 changes[*] <|@
BUG=
R=verwaest@chromium.org, danno@chromium.org
Review URL: https://codereview.chromium.org/104663004
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18626 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-15 17:00:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class HydrogenCodeStub : public CodeStub {
|
|
|
|
public:
|
2013-04-18 20:37:27 +00:00
|
|
|
enum InitializationState {
|
2013-05-24 11:44:55 +00:00
|
|
|
UNINITIALIZED,
|
|
|
|
INITIALIZED
|
2013-04-18 20:37:27 +00:00
|
|
|
};
|
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
HydrogenCodeStub(Isolate* isolate, InitializationState state = INITIALIZED)
|
|
|
|
: CodeStub(isolate) {
|
2013-05-24 11:44:55 +00:00
|
|
|
is_uninitialized_ = (state == UNINITIALIZED);
|
2013-04-18 20:37:27 +00:00
|
|
|
}
|
2012-12-18 16:25:45 +00:00
|
|
|
|
2013-04-18 09:50:46 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::STUB; }
|
2012-12-18 16:25:45 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* GetInterfaceDescriptor() {
|
|
|
|
return isolate()->code_stub_interface_descriptor(MajorKey());
|
2012-12-18 16:25:45 +00:00
|
|
|
}
|
|
|
|
|
2013-05-24 11:44:55 +00:00
|
|
|
bool IsUninitialized() { return is_uninitialized_; }
|
2013-04-18 20:37:27 +00:00
|
|
|
|
|
|
|
template<class SubClass>
|
|
|
|
static Handle<Code> GetUninitialized(Isolate* isolate) {
|
|
|
|
SubClass::GenerateAheadOfTime(isolate);
|
|
|
|
return SubClass().GetCode(isolate);
|
|
|
|
}
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) = 0;
|
2013-04-18 20:37:27 +00:00
|
|
|
|
|
|
|
// Retrieve the code for the stub. Generate the code if needed.
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() = 0;
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual int NotMissMinorKey() const = 0;
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
Handle<Code> GenerateLightweightMissCode();
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2013-07-05 09:26:22 +00:00
|
|
|
template<class StateType>
|
|
|
|
void TraceTransition(StateType from, StateType to);
|
|
|
|
|
2013-04-18 20:37:27 +00:00
|
|
|
private:
|
|
|
|
class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
|
|
|
|
class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
|
|
|
|
|
|
|
|
void GenerateLightweightMiss(MacroAssembler* masm);
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual int MinorKey() const {
|
2013-05-24 11:44:55 +00:00
|
|
|
return IsMissBits::encode(is_uninitialized_) |
|
2013-04-18 20:37:27 +00:00
|
|
|
MinorKeyBits::encode(NotMissMinorKey());
|
|
|
|
}
|
|
|
|
|
2013-05-24 11:44:55 +00:00
|
|
|
bool is_uninitialized_;
|
2012-12-18 16:25:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
// 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);
|
|
|
|
};
|
|
|
|
|
2013-07-19 11:52:42 +00:00
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#if V8_TARGET_ARCH_IA32
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/ia32/code-stubs-ia32.h"
|
2010-08-30 11:48:07 +00:00
|
|
|
#elif V8_TARGET_ARCH_X64
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/x64/code-stubs-x64.h"
|
2014-03-21 09:28:26 +00:00
|
|
|
#elif V8_TARGET_ARCH_ARM64
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/arm64/code-stubs-arm64.h"
|
2010-08-30 11:48:07 +00:00
|
|
|
#elif V8_TARGET_ARCH_ARM
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/arm/code-stubs-arm.h"
|
2010-08-30 11:48:07 +00:00
|
|
|
#elif V8_TARGET_ARCH_MIPS
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/mips/code-stubs-mips.h"
|
2014-07-09 11:08:26 +00:00
|
|
|
#elif V8_TARGET_ARCH_MIPS64
|
|
|
|
#include "src/mips64/code-stubs-mips64.h"
|
2014-05-23 16:37:27 +00:00
|
|
|
#elif V8_TARGET_ARCH_X87
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/x87/code-stubs-x87.h"
|
2010-08-30 11:48:07 +00:00
|
|
|
#else
|
|
|
|
#error Unsupported target architecture.
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
// RuntimeCallHelper implementation used in stubs: enters/leaves a
|
2010-08-30 11:48:07 +00:00
|
|
|
// newly created internal frame before/after the runtime call.
|
2010-12-07 11:31:57 +00:00
|
|
|
class StubRuntimeCallHelper : public RuntimeCallHelper {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2010-12-07 11:31:57 +00:00
|
|
|
StubRuntimeCallHelper() {}
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
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 {}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-07-23 06:02:54 +00:00
|
|
|
class ToNumberStub: public HydrogenCodeStub {
|
2011-01-28 14:18:26 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
|
2011-01-28 14:18:26 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-07-23 06:02:54 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2011-01-28 14:18:26 +00:00
|
|
|
|
2014-02-21 11:19:32 +00:00
|
|
|
static void InstallDescriptors(Isolate* isolate) {
|
2014-04-24 06:25:42 +00:00
|
|
|
ToNumberStub stub(isolate);
|
2014-02-21 11:19:32 +00:00
|
|
|
stub.InitializeInterfaceDescriptor(
|
|
|
|
isolate->code_stub_interface_descriptor(CodeStub::ToNumber));
|
|
|
|
}
|
|
|
|
|
2011-01-28 14:18:26 +00:00
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ToNumber; }
|
|
|
|
int NotMissMinorKey() const { return 0; }
|
2011-01-28 14:18:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-09-24 09:31:07 +00:00
|
|
|
class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
|
2013-09-24 09:31:07 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-09-24 09:31:07 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
2013-10-21 12:42:08 +00:00
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
2013-09-24 09:31:07 +00:00
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int kNumber = 0;
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE { return NumberToString; }
|
|
|
|
virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; }
|
2013-09-24 09:31:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-08-27 11:55:08 +00:00
|
|
|
class FastNewClosureStub : public HydrogenCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
FastNewClosureStub(Isolate* isolate,
|
|
|
|
StrictMode strict_mode,
|
|
|
|
bool is_generator)
|
|
|
|
: HydrogenCodeStub(isolate),
|
|
|
|
strict_mode_(strict_mode),
|
|
|
|
is_generator_(is_generator) { }
|
2011-03-17 20:28:30 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-08-27 11:55:08 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-08-27 11:55:08 +00:00
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
2014-03-11 14:41:22 +00:00
|
|
|
StrictMode strict_mode() const { return strict_mode_; }
|
2013-08-27 11:55:08 +00:00
|
|
|
bool is_generator() const { return is_generator_; }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
private:
|
2013-04-11 16:28:19 +00:00
|
|
|
class StrictModeBits: public BitField<bool, 0, 1> {};
|
|
|
|
class IsGeneratorBits: public BitField<bool, 1, 1> {};
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return FastNewClosure; }
|
|
|
|
int NotMissMinorKey() const {
|
2014-03-11 14:41:22 +00:00
|
|
|
return StrictModeBits::encode(strict_mode_ == STRICT) |
|
2013-04-11 16:28:19 +00:00
|
|
|
IsGeneratorBits::encode(is_generator_);
|
|
|
|
}
|
2011-03-17 20:28:30 +00:00
|
|
|
|
2014-03-11 14:41:22 +00:00
|
|
|
StrictMode strict_mode_;
|
2013-04-11 16:28:19 +00:00
|
|
|
bool is_generator_;
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-23 08:36:22 +00:00
|
|
|
class FastNewContextStub V8_FINAL : public HydrogenCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2011-01-25 13:01:45 +00:00
|
|
|
static const int kMaximumSlots = 64;
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
FastNewContextStub(Isolate* isolate, int slots)
|
|
|
|
: HydrogenCodeStub(isolate), slots_(slots) {
|
2011-10-06 15:59:02 +00:00
|
|
|
ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
|
2010-08-30 11:48:07 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2014-01-23 08:36:22 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2014-01-23 08:36:22 +00:00
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
int slots() const { return slots_; }
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE { return FastNewContext; }
|
|
|
|
virtual int NotMissMinorKey() const V8_OVERRIDE { return slots_; }
|
2014-01-23 08:36:22 +00:00
|
|
|
|
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int kFunction = 0;
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
private:
|
2011-01-21 11:28:35 +00:00
|
|
|
int slots_;
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-04-04 17:55:43 +00:00
|
|
|
class FastCloneShallowArrayStub : public HydrogenCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
FastCloneShallowArrayStub(Isolate* isolate,
|
2014-05-12 07:49:11 +00:00
|
|
|
AllocationSiteMode allocation_site_mode)
|
2014-04-24 06:25:42 +00:00
|
|
|
: HydrogenCodeStub(isolate),
|
2014-05-12 07:49:11 +00:00
|
|
|
allocation_site_mode_(allocation_site_mode) {}
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2013-04-04 17:55:43 +00:00
|
|
|
AllocationSiteMode allocation_site_mode() const {
|
|
|
|
return allocation_site_mode_;
|
|
|
|
}
|
|
|
|
|
2014-05-12 07:49:11 +00:00
|
|
|
virtual Handle<Code> GenerateCode();
|
2013-04-04 17:55:43 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2014-02-21 11:19:32 +00:00
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
private:
|
2013-01-17 08:41:27 +00:00
|
|
|
AllocationSiteMode allocation_site_mode_;
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2013-01-17 08:41:27 +00:00
|
|
|
class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
|
|
|
|
// Ensure data fits within available bits.
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return FastCloneShallowArray; }
|
|
|
|
int NotMissMinorKey() const {
|
2014-05-12 07:49:11 +00:00
|
|
|
return AllocationSiteModeBits::encode(allocation_site_mode_);
|
2010-08-30 11:48:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-26 13:08:08 +00:00
|
|
|
class FastCloneShallowObjectStub : public HydrogenCodeStub {
|
2011-11-21 13:27:44 +00:00
|
|
|
public:
|
|
|
|
// Maximum number of properties in copied object.
|
|
|
|
static const int kMaximumClonedProperties = 6;
|
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
FastCloneShallowObjectStub(Isolate* isolate, int length)
|
|
|
|
: HydrogenCodeStub(isolate), length_(length) {
|
2011-11-21 13:27:44 +00:00
|
|
|
ASSERT_GE(length_, 0);
|
|
|
|
ASSERT_LE(length_, kMaximumClonedProperties);
|
|
|
|
}
|
|
|
|
|
2013-02-26 13:08:08 +00:00
|
|
|
int length() const { return length_; }
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-02-26 13:08:08 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2011-11-21 13:27:44 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
int length_;
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return FastCloneShallowObject; }
|
|
|
|
int NotMissMinorKey() const { return length_; }
|
2013-02-26 13:08:08 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
|
2011-11-21 13:27:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-07-08 10:02:16 +00:00
|
|
|
class CreateAllocationSiteStub : public HydrogenCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit CreateAllocationSiteStub(Isolate* isolate)
|
|
|
|
: HydrogenCodeStub(isolate) { }
|
2013-07-08 10:02:16 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-07-08 10:02:16 +00:00
|
|
|
|
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-07-08 10:02:16 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return CreateAllocationSite; }
|
|
|
|
int NotMissMinorKey() const { return 0; }
|
2013-07-08 10:02:16 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class InstanceofStub: public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2010-12-16 08:58:42 +00:00
|
|
|
enum Flags {
|
|
|
|
kNoFlags = 0,
|
2011-01-05 11:17:37 +00:00
|
|
|
kArgsInRegisters = 1 << 0,
|
|
|
|
kCallSiteInlineCheck = 1 << 1,
|
|
|
|
kReturnTrueFalseObject = 1 << 2
|
2010-12-16 08:58:42 +00:00
|
|
|
};
|
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
InstanceofStub(Isolate* isolate, Flags flags)
|
|
|
|
: PlatformCodeStub(isolate), flags_(flags) { }
|
2011-01-05 11:17:37 +00:00
|
|
|
|
|
|
|
static Register left();
|
|
|
|
static Register right();
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate, CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return Instanceof; }
|
|
|
|
int MinorKey() const { return static_cast<int>(flags_); }
|
2010-12-16 08:58:42 +00:00
|
|
|
|
2011-01-05 11:17:37 +00:00
|
|
|
bool HasArgsInRegisters() const {
|
2010-12-16 08:58:42 +00:00
|
|
|
return (flags_ & kArgsInRegisters) != 0;
|
|
|
|
}
|
|
|
|
|
2011-01-05 11:17:37 +00:00
|
|
|
bool HasCallSiteInlineCheck() const {
|
|
|
|
return (flags_ & kCallSiteInlineCheck) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReturnTrueFalseObject() const {
|
|
|
|
return (flags_ & kReturnTrueFalseObject) != 0;
|
|
|
|
}
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
|
2011-01-05 11:17:37 +00:00
|
|
|
|
2010-12-16 08:58:42 +00:00
|
|
|
Flags flags_;
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-09-12 17:59:41 +00:00
|
|
|
enum AllocationSiteOverrideMode {
|
|
|
|
DONT_OVERRIDE,
|
|
|
|
DISABLE_ALLOCATION_SITES,
|
|
|
|
LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
class ArrayConstructorStub: public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
|
|
|
|
ArrayConstructorStub(Isolate* isolate, int argument_count);
|
|
|
|
explicit ArrayConstructorStub(Isolate* isolate);
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
2013-09-12 17:59:41 +00:00
|
|
|
void GenerateDispatchToArrayStub(MacroAssembler* masm,
|
|
|
|
AllocationSiteOverrideMode mode);
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
|
2013-09-12 17:59:41 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return ArrayConstructor; }
|
|
|
|
virtual int MinorKey() const { return argument_count_; }
|
2013-04-25 16:00:32 +00:00
|
|
|
|
|
|
|
ArgumentCountKey argument_count_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-06-05 10:43:18 +00:00
|
|
|
class InternalArrayConstructorStub: public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
explicit InternalArrayConstructorStub(Isolate* isolate);
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return InternalArrayConstructor; }
|
|
|
|
virtual int MinorKey() const { return 0; }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
void GenerateCase(MacroAssembler* masm, ElementsKind kind);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class MathPowStub: public PlatformCodeStub {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2013-05-27 13:59:20 +00:00
|
|
|
enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
|
2011-12-02 08:06:37 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
MathPowStub(Isolate* isolate, ExponentType exponent_type)
|
|
|
|
: PlatformCodeStub(isolate), exponent_type_(exponent_type) { }
|
2010-12-07 11:31:57 +00:00
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return MathPow; }
|
|
|
|
virtual int MinorKey() const { return exponent_type_; }
|
2011-12-02 08:06:37 +00:00
|
|
|
|
|
|
|
ExponentType exponent_type_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-01-21 14:53:29 +00:00
|
|
|
class ICStub: public PlatformCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
ICStub(Isolate* isolate, Code::Kind kind)
|
|
|
|
: PlatformCodeStub(isolate), kind_(kind) { }
|
2013-04-18 09:50:46 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return kind_; }
|
2013-02-04 15:40:50 +00:00
|
|
|
virtual InlineCacheState GetICState() { return MONOMORPHIC; }
|
2013-01-21 14:53:29 +00:00
|
|
|
|
2014-07-21 13:10:14 +00:00
|
|
|
bool Describes(Code* code) { return code->stub_key() == GetKey(); }
|
2013-01-21 14:53:29 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
class KindBits: public BitField<Code::Kind, 0, 4> {};
|
2014-07-03 07:18:30 +00:00
|
|
|
Code::Kind kind() const { return kind_; }
|
2013-01-21 14:53:29 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual int MinorKey() const { return KindBits::encode(kind_); }
|
2013-01-21 17:17:02 +00:00
|
|
|
|
2013-01-21 14:53:29 +00:00
|
|
|
private:
|
|
|
|
Code::Kind kind_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-04-30 14:33:35 +00:00
|
|
|
class CallICStub: public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
CallICStub(Isolate* isolate, const CallIC::State& state)
|
|
|
|
: PlatformCodeStub(isolate), state_(state) {}
|
|
|
|
|
|
|
|
bool CallAsMethod() const { return state_.CallAsMethod(); }
|
|
|
|
|
|
|
|
int arg_count() const { return state_.arg_count(); }
|
|
|
|
|
|
|
|
static int ExtractArgcFromMinorKey(int minor_key) {
|
|
|
|
CallIC::State state((ExtraICState) minor_key);
|
|
|
|
return state.arg_count();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
|
|
|
|
return Code::CALL_IC;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE {
|
|
|
|
return state_.GetICState();
|
|
|
|
}
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const V8_FINAL V8_OVERRIDE {
|
2014-04-30 14:33:35 +00:00
|
|
|
return state_.GetExtraICState();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual int MinorKey() const { return GetExtraICState(); }
|
|
|
|
virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
|
2014-04-30 14:33:35 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return CallIC; }
|
2014-04-30 14:33:35 +00:00
|
|
|
|
|
|
|
// Code generation helpers.
|
2014-05-28 11:29:55 +00:00
|
|
|
void GenerateMiss(MacroAssembler* masm, IC::UtilityId id);
|
|
|
|
|
|
|
|
const CallIC::State state_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CallIC_ArrayStub: public CallICStub {
|
|
|
|
public:
|
|
|
|
CallIC_ArrayStub(Isolate* isolate, const CallIC::State& state_in)
|
|
|
|
: CallICStub(isolate, state_in) {}
|
|
|
|
|
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
protected:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
|
2014-04-30 14:33:35 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return CallIC_Array; }
|
2014-04-30 14:33:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-22 14:27:53 +00:00
|
|
|
// TODO(verwaest): Translate to hydrogen code stub.
|
|
|
|
class FunctionPrototypeStub : public PlatformCodeStub {
|
2013-01-21 17:54:36 +00:00
|
|
|
public:
|
2014-07-25 17:50:53 +00:00
|
|
|
explicit FunctionPrototypeStub(Isolate* isolate)
|
|
|
|
: PlatformCodeStub(isolate) {}
|
2013-01-21 17:54:36 +00:00
|
|
|
virtual void Generate(MacroAssembler* masm);
|
2014-07-22 14:27:53 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
|
2013-01-21 17:54:36 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return FunctionPrototype; }
|
2014-07-25 17:50:53 +00:00
|
|
|
virtual int MinorKey() const { return 0; }
|
2013-01-21 17:54:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-01-25 11:55:29 +00:00
|
|
|
class StoreICStub: public ICStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
StoreICStub(Isolate* isolate, Code::Kind kind, StrictMode strict_mode)
|
|
|
|
: ICStub(isolate, kind), strict_mode_(strict_mode) { }
|
2013-01-25 11:55:29 +00:00
|
|
|
|
|
|
|
protected:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const {
|
2013-11-28 15:32:55 +00:00
|
|
|
return StoreIC::ComputeExtraICState(strict_mode_);
|
2013-01-25 11:55:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2013-03-04 14:03:27 +00:00
|
|
|
STATIC_ASSERT(KindBits::kSize == 4);
|
2013-01-25 11:55:29 +00:00
|
|
|
class StrictModeBits: public BitField<bool, 4, 1> {};
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual int MinorKey() const {
|
2013-01-25 11:55:29 +00:00
|
|
|
return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
|
|
|
|
}
|
|
|
|
|
2014-03-11 14:41:22 +00:00
|
|
|
StrictMode strict_mode_;
|
2013-01-25 11:55:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-02 16:32:47 +00:00
|
|
|
class HICStub: public HydrogenCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit HICStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
|
2013-05-02 16:32:47 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return kind(); }
|
|
|
|
virtual InlineCacheState GetICState() { return MONOMORPHIC; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
class KindBits: public BitField<Code::Kind, 0, 4> {};
|
|
|
|
virtual Code::Kind kind() const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class HandlerStub: public HICStub {
|
2013-03-04 14:03:27 +00:00
|
|
|
public:
|
2013-09-30 13:53:21 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const { return kind(); }
|
2013-11-15 10:52:05 +00:00
|
|
|
|
|
|
|
protected:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit HandlerStub(Isolate* isolate) : HICStub(isolate) { }
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual int NotMissMinorKey() const { return bit_field_; }
|
2013-11-15 10:52:05 +00:00
|
|
|
int bit_field_;
|
2013-03-04 14:03:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LoadFieldStub: public HandlerStub {
|
|
|
|
public:
|
2014-06-10 14:01:08 +00:00
|
|
|
LoadFieldStub(Isolate* isolate, FieldIndex index)
|
|
|
|
: HandlerStub(isolate), index_(index) {
|
|
|
|
Initialize(Code::LOAD_IC);
|
2013-05-02 16:32:47 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-05-02 16:32:47 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-05-02 16:32:47 +00:00
|
|
|
|
|
|
|
Representation representation() {
|
2013-05-08 15:02:08 +00:00
|
|
|
if (unboxed_double()) return Representation::Double();
|
2013-05-02 16:32:47 +00:00
|
|
|
return Representation::Tagged();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Code::Kind kind() const {
|
|
|
|
return KindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2014-06-10 14:01:08 +00:00
|
|
|
FieldIndex index() const { return index_; }
|
2013-03-04 14:03:27 +00:00
|
|
|
|
2013-05-08 15:02:08 +00:00
|
|
|
bool unboxed_double() {
|
2014-06-10 14:01:08 +00:00
|
|
|
return index_.is_double();
|
2013-05-08 15:02:08 +00:00
|
|
|
}
|
|
|
|
|
2013-11-19 12:04:54 +00:00
|
|
|
virtual Code::StubType GetStubType() { return Code::FAST; }
|
2013-03-04 14:03:27 +00:00
|
|
|
|
2013-05-02 16:32:47 +00:00
|
|
|
protected:
|
2014-06-10 14:01:08 +00:00
|
|
|
explicit LoadFieldStub(Isolate* isolate);
|
|
|
|
|
|
|
|
void Initialize(Code::Kind kind) {
|
|
|
|
int property_index_key = index_.GetLoadFieldStubKey();
|
|
|
|
// Save a copy of the essence of the property index into the bit field to
|
|
|
|
// make sure that hashing of unique stubs works correctly..
|
|
|
|
bit_field_ = KindBits::encode(kind) |
|
|
|
|
EncodedLoadFieldByIndexBits::encode(property_index_key);
|
2013-05-02 16:32:47 +00:00
|
|
|
}
|
|
|
|
|
2013-03-04 14:03:27 +00:00
|
|
|
private:
|
|
|
|
STATIC_ASSERT(KindBits::kSize == 4);
|
2014-06-10 14:01:08 +00:00
|
|
|
class EncodedLoadFieldByIndexBits: public BitField<int, 4, 13> {};
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return LoadField; }
|
2014-06-10 14:01:08 +00:00
|
|
|
FieldIndex index_;
|
2013-05-02 16:32:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-03-13 10:57:07 +00:00
|
|
|
class StringLengthStub: public HandlerStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {
|
2014-03-13 10:57:07 +00:00
|
|
|
Initialize(Code::LOAD_IC);
|
|
|
|
}
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2014-03-13 10:57:07 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2014-03-13 10:57:07 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual Code::Kind kind() const {
|
|
|
|
return KindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Initialize(Code::Kind kind) {
|
|
|
|
bit_field_ = KindBits::encode(kind);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return StringLength; }
|
2014-03-13 10:57:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-11-07 10:17:13 +00:00
|
|
|
class StoreGlobalStub : public HandlerStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
|
|
|
|
: HandlerStub(isolate) {
|
2014-03-10 12:23:05 +00:00
|
|
|
bit_field_ = IsConstantBits::encode(is_constant) |
|
|
|
|
CheckGlobalBits::encode(check_global);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Handle<HeapObject> global_placeholder(Isolate* isolate) {
|
|
|
|
return isolate->factory()->uninitialized_value();
|
2013-11-07 10:17:13 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
|
2014-03-18 14:15:09 +00:00
|
|
|
Handle<PropertyCell> cell) {
|
2014-03-10 12:23:05 +00:00
|
|
|
if (check_global()) {
|
2014-03-18 14:15:09 +00:00
|
|
|
Code::FindAndReplacePattern pattern;
|
2014-04-24 12:07:40 +00:00
|
|
|
pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
|
|
|
|
pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
|
|
|
|
pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
|
|
|
|
return CodeStub::GetCodeCopy(pattern);
|
2014-03-18 14:15:09 +00:00
|
|
|
} else {
|
|
|
|
Code::FindAndReplacePattern pattern;
|
2014-04-24 12:07:40 +00:00
|
|
|
pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
|
|
|
|
return CodeStub::GetCodeCopy(pattern);
|
2014-03-10 12:23:05 +00:00
|
|
|
}
|
2013-11-07 10:17:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Code::Kind kind() const { return Code::STORE_IC; }
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-11-07 10:17:13 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-11-07 10:17:13 +00:00
|
|
|
|
2014-03-10 12:23:05 +00:00
|
|
|
bool is_constant() const {
|
2013-11-07 10:17:13 +00:00
|
|
|
return IsConstantBits::decode(bit_field_);
|
|
|
|
}
|
2014-03-10 12:23:05 +00:00
|
|
|
bool check_global() const {
|
|
|
|
return CheckGlobalBits::decode(bit_field_);
|
|
|
|
}
|
2013-11-07 10:17:13 +00:00
|
|
|
void set_is_constant(bool value) {
|
|
|
|
bit_field_ = IsConstantBits::update(bit_field_, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
Representation representation() {
|
|
|
|
return Representation::FromKind(RepresentationBits::decode(bit_field_));
|
|
|
|
}
|
|
|
|
void set_representation(Representation r) {
|
|
|
|
bit_field_ = RepresentationBits::update(bit_field_, r.kind());
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return StoreGlobal; }
|
2013-11-07 10:17:13 +00:00
|
|
|
|
2013-11-27 14:00:54 +00:00
|
|
|
class IsConstantBits: public BitField<bool, 0, 1> {};
|
|
|
|
class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
|
2014-03-10 12:23:05 +00:00
|
|
|
class CheckGlobalBits: public BitField<bool, 9, 1> {};
|
2013-11-07 10:17:13 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-27 09:57:54 +00:00
|
|
|
class CallApiFunctionStub : public PlatformCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
CallApiFunctionStub(Isolate* isolate,
|
|
|
|
bool is_store,
|
2014-01-27 09:57:54 +00:00
|
|
|
bool call_data_undefined,
|
2014-04-24 06:25:42 +00:00
|
|
|
int argc) : PlatformCodeStub(isolate) {
|
2014-01-27 09:57:54 +00:00
|
|
|
bit_field_ =
|
2014-02-14 14:13:06 +00:00
|
|
|
IsStoreBits::encode(is_store) |
|
2014-01-27 09:57:54 +00:00
|
|
|
CallDataUndefinedBits::encode(call_data_undefined) |
|
|
|
|
ArgumentBits::encode(argc);
|
2014-02-14 14:13:06 +00:00
|
|
|
ASSERT(!is_store || argc == 1);
|
2014-01-27 09:57:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE { return CallApiFunction; }
|
|
|
|
virtual int MinorKey() const V8_OVERRIDE { return bit_field_; }
|
2014-01-27 09:57:54 +00:00
|
|
|
|
2014-02-14 14:13:06 +00:00
|
|
|
class IsStoreBits: public BitField<bool, 0, 1> {};
|
2014-01-27 09:57:54 +00:00
|
|
|
class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
|
|
|
|
class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
|
|
|
|
|
|
|
|
int bit_field_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(CallApiFunctionStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-30 12:15:51 +00:00
|
|
|
class CallApiGetterStub : public PlatformCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
2014-01-30 12:15:51 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE { return CallApiGetter; }
|
|
|
|
virtual int MinorKey() const V8_OVERRIDE { return 0; }
|
2014-01-30 12:15:51 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(CallApiGetterStub);
|
|
|
|
};
|
2013-03-04 14:03:27 +00:00
|
|
|
|
|
|
|
|
2014-01-02 15:31:27 +00:00
|
|
|
class BinaryOpICStub : public HydrogenCodeStub {
|
2012-11-14 15:59:45 +00:00
|
|
|
public:
|
2014-07-30 13:54:45 +00:00
|
|
|
BinaryOpICStub(Isolate* isolate, Token::Value op,
|
|
|
|
OverwriteMode mode = NO_OVERWRITE)
|
2014-04-25 08:40:23 +00:00
|
|
|
: HydrogenCodeStub(isolate, UNINITIALIZED), state_(isolate, op, mode) {}
|
2013-10-04 08:17:11 +00:00
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
explicit BinaryOpICStub(Isolate* isolate, const BinaryOpIC::State& state)
|
2014-04-24 06:25:42 +00:00
|
|
|
: HydrogenCodeStub(isolate), state_(state) {}
|
2012-11-14 15:59:45 +00:00
|
|
|
|
2013-10-04 08:17:11 +00:00
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
2013-12-02 13:14:07 +00:00
|
|
|
|
2013-10-04 08:17:11 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2012-11-14 15:59:45 +00:00
|
|
|
|
2013-12-02 13:14:07 +00:00
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
2012-11-14 15:59:45 +00:00
|
|
|
|
2014-01-02 09:28:53 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
|
2013-12-02 13:14:07 +00:00
|
|
|
return Code::BINARY_OP_IC;
|
2013-10-10 08:45:40 +00:00
|
|
|
}
|
|
|
|
|
2014-01-02 15:31:27 +00:00
|
|
|
virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE {
|
2013-12-02 13:14:07 +00:00
|
|
|
return state_.GetICState();
|
2013-06-04 07:49:45 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const V8_FINAL V8_OVERRIDE {
|
2013-12-02 13:14:07 +00:00
|
|
|
return state_.GetExtraICState();
|
2013-10-01 18:00:02 +00:00
|
|
|
}
|
2013-06-04 07:49:45 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2012-11-14 15:59:45 +00:00
|
|
|
|
2013-12-02 13:14:07 +00:00
|
|
|
const BinaryOpIC::State& state() const { return state_; }
|
2013-06-04 07:49:45 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintState(OStream& os) const V8_FINAL V8_OVERRIDE; // NOLINT
|
2014-01-02 15:31:27 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE { return BinaryOpIC; }
|
|
|
|
virtual int NotMissMinorKey() const V8_FINAL V8_OVERRIDE {
|
2014-01-02 15:31:27 +00:00
|
|
|
return GetExtraICState();
|
|
|
|
}
|
2013-06-04 07:49:45 +00:00
|
|
|
|
2013-12-02 13:14:07 +00:00
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int kLeft = 0;
|
|
|
|
static const int kRight = 1;
|
2013-10-04 08:17:11 +00:00
|
|
|
|
|
|
|
private:
|
2013-12-02 13:14:07 +00:00
|
|
|
static void GenerateAheadOfTime(Isolate* isolate,
|
|
|
|
const BinaryOpIC::State& state);
|
2013-10-04 08:17:11 +00:00
|
|
|
|
2014-01-02 09:17:52 +00:00
|
|
|
BinaryOpIC::State state_;
|
|
|
|
|
2014-01-02 10:38:45 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub);
|
2014-01-02 09:17:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-02 15:31:27 +00:00
|
|
|
// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
|
|
|
|
// call support for stubs in Hydrogen.
|
|
|
|
class BinaryOpICWithAllocationSiteStub V8_FINAL : public PlatformCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
BinaryOpICWithAllocationSiteStub(Isolate* isolate,
|
|
|
|
const BinaryOpIC::State& state)
|
|
|
|
: PlatformCodeStub(isolate), state_(state) {}
|
2014-01-02 15:31:27 +00:00
|
|
|
|
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
|
2014-03-18 14:15:09 +00:00
|
|
|
Code::FindAndReplacePattern pattern;
|
2014-04-24 12:07:40 +00:00
|
|
|
pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
|
|
|
|
return CodeStub::GetCodeCopy(pattern);
|
2014-01-02 15:31:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
|
|
|
|
return Code::BINARY_OP_IC;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual InlineCacheState GetICState() V8_OVERRIDE {
|
|
|
|
return state_.GetICState();
|
|
|
|
}
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const V8_OVERRIDE {
|
2014-01-02 15:31:27 +00:00
|
|
|
return state_.GetExtraICState();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
|
2014-01-02 15:31:27 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE {
|
|
|
|
return BinaryOpICWithAllocationSite;
|
|
|
|
}
|
|
|
|
virtual int MinorKey() const V8_OVERRIDE { return GetExtraICState(); }
|
2014-01-02 15:31:27 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
static void GenerateAheadOfTime(Isolate* isolate,
|
|
|
|
const BinaryOpIC::State& state);
|
|
|
|
|
|
|
|
BinaryOpIC::State state_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(BinaryOpICWithAllocationSiteStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class BinaryOpWithAllocationSiteStub V8_FINAL : public BinaryOpICStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
BinaryOpWithAllocationSiteStub(Isolate* isolate,
|
|
|
|
Token::Value op,
|
|
|
|
OverwriteMode mode)
|
|
|
|
: BinaryOpICStub(isolate, op, mode) {}
|
2014-01-09 13:22:18 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
BinaryOpWithAllocationSiteStub(Isolate* isolate,
|
|
|
|
const BinaryOpIC::State& state)
|
|
|
|
: BinaryOpICStub(isolate, state) {}
|
2014-01-02 15:31:27 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2014-01-02 15:31:27 +00:00
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
virtual Code::Kind GetCodeKind() const V8_FINAL V8_OVERRIDE {
|
|
|
|
return Code::STUB;
|
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2014-01-02 15:31:27 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE {
|
2014-01-02 15:31:27 +00:00
|
|
|
return BinaryOpWithAllocationSite;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int kAllocationSite = 0;
|
|
|
|
static const int kLeft = 1;
|
|
|
|
static const int kRight = 2;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-22 13:48:05 +00:00
|
|
|
enum StringAddFlags {
|
|
|
|
// Omit both parameter checks.
|
|
|
|
STRING_ADD_CHECK_NONE = 0,
|
|
|
|
// Check left parameter.
|
|
|
|
STRING_ADD_CHECK_LEFT = 1 << 0,
|
|
|
|
// Check right parameter.
|
|
|
|
STRING_ADD_CHECK_RIGHT = 1 << 1,
|
|
|
|
// Check both parameters.
|
|
|
|
STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class StringAddStub V8_FINAL : public HydrogenCodeStub {
|
2013-11-12 10:21:08 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
StringAddStub(Isolate* isolate,
|
|
|
|
StringAddFlags flags,
|
|
|
|
PretenureFlag pretenure_flag)
|
|
|
|
: HydrogenCodeStub(isolate),
|
|
|
|
bit_field_(StringAddFlagsBits::encode(flags) |
|
2013-11-12 10:21:08 +00:00
|
|
|
PretenureFlagBits::encode(pretenure_flag)) {}
|
|
|
|
|
|
|
|
StringAddFlags flags() const {
|
|
|
|
return StringAddFlagsBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
PretenureFlag pretenure_flag() const {
|
|
|
|
return PretenureFlagBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-11-12 10:21:08 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int kLeft = 0;
|
|
|
|
static const int kRight = 1;
|
|
|
|
|
|
|
|
private:
|
|
|
|
class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
|
|
|
|
class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
|
|
|
|
uint32_t bit_field_;
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE { return StringAdd; }
|
|
|
|
virtual int NotMissMinorKey() const V8_OVERRIDE { return bit_field_; }
|
2013-11-12 10:21:08 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintBaseName(OStream& os) const V8_OVERRIDE; // NOLINT
|
2013-11-12 10:21:08 +00:00
|
|
|
|
2014-01-22 13:48:05 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(StringAddStub);
|
2013-11-12 10:21:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class ICCompareStub: public PlatformCodeStub {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
ICCompareStub(Isolate* isolate,
|
|
|
|
Token::Value op,
|
2012-11-14 15:59:45 +00:00
|
|
|
CompareIC::State left,
|
|
|
|
CompareIC::State right,
|
|
|
|
CompareIC::State handler)
|
2014-04-24 06:25:42 +00:00
|
|
|
: PlatformCodeStub(isolate),
|
|
|
|
op_(op),
|
2012-11-14 15:59:45 +00:00
|
|
|
left_(left),
|
|
|
|
right_(right),
|
|
|
|
state_(handler) {
|
2010-12-07 11:31:57 +00:00
|
|
|
ASSERT(Token::IsCompareOp(op));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
2011-12-09 09:26:14 +00:00
|
|
|
void set_known_map(Handle<Map> map) { known_map_ = map; }
|
|
|
|
|
2014-07-21 13:10:14 +00:00
|
|
|
static void DecodeKey(uint32_t stub_key, CompareIC::State* left_state,
|
|
|
|
CompareIC::State* right_state,
|
|
|
|
CompareIC::State* handler_state, Token::Value* op);
|
2012-11-14 15:59:45 +00:00
|
|
|
|
2013-06-07 13:11:17 +00:00
|
|
|
virtual InlineCacheState GetICState();
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
private:
|
|
|
|
class OpField: public BitField<int, 0, 3> { };
|
2013-03-01 13:28:55 +00:00
|
|
|
class LeftStateField: public BitField<int, 3, 4> { };
|
|
|
|
class RightStateField: public BitField<int, 7, 4> { };
|
|
|
|
class HandlerStateField: public BitField<int, 11, 4> { };
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return CompareIC; }
|
|
|
|
virtual int MinorKey() const;
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2013-04-18 09:50:46 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
void GenerateSmis(MacroAssembler* masm);
|
2013-02-28 14:43:57 +00:00
|
|
|
void GenerateNumbers(MacroAssembler* masm);
|
2013-02-28 17:03:34 +00:00
|
|
|
void GenerateInternalizedStrings(MacroAssembler* masm);
|
2011-05-04 18:30:37 +00:00
|
|
|
void GenerateStrings(MacroAssembler* masm);
|
2013-03-01 13:28:55 +00:00
|
|
|
void GenerateUniqueNames(MacroAssembler* masm);
|
2010-12-07 11:31:57 +00:00
|
|
|
void GenerateObjects(MacroAssembler* masm);
|
|
|
|
void GenerateMiss(MacroAssembler* masm);
|
2011-12-09 09:26:14 +00:00
|
|
|
void GenerateKnownObjects(MacroAssembler* masm);
|
2012-11-14 15:59:45 +00:00
|
|
|
void GenerateGeneric(MacroAssembler* masm);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
bool strict() const { return op_ == Token::EQ_STRICT; }
|
|
|
|
Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
|
|
|
|
|
2011-12-09 09:26:14 +00:00
|
|
|
virtual void AddToSpecialCache(Handle<Code> new_object);
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual bool FindCodeInSpecialCache(Code** code_out);
|
2013-02-28 14:43:57 +00:00
|
|
|
virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
|
2011-12-09 09:26:14 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
Token::Value op_;
|
2012-11-14 15:59:45 +00:00
|
|
|
CompareIC::State left_;
|
|
|
|
CompareIC::State right_;
|
2010-12-07 11:31:57 +00:00
|
|
|
CompareIC::State state_;
|
2011-12-09 09:26:14 +00:00
|
|
|
Handle<Map> known_map_;
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-04-24 11:32:17 +00:00
|
|
|
class CompareNilICStub : public HydrogenCodeStub {
|
|
|
|
public:
|
2014-01-21 16:22:52 +00:00
|
|
|
Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
|
|
|
|
Type* GetInputType(Zone* zone, Handle<Map> map);
|
2013-05-16 10:59:17 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
CompareNilICStub(Isolate* isolate, NilValue nil)
|
|
|
|
: HydrogenCodeStub(isolate), nil_value_(nil) { }
|
2013-04-24 11:32:17 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
CompareNilICStub(Isolate* isolate,
|
|
|
|
ExtraICState ic_state,
|
2013-05-24 11:44:55 +00:00
|
|
|
InitializationState init_state = INITIALIZED)
|
2014-04-24 06:25:42 +00:00
|
|
|
: HydrogenCodeStub(isolate, init_state),
|
2013-07-11 17:20:57 +00:00
|
|
|
nil_value_(NilValueField::decode(ic_state)),
|
|
|
|
state_(State(TypesField::decode(ic_state))) {
|
|
|
|
}
|
2013-04-24 11:32:17 +00:00
|
|
|
|
|
|
|
static Handle<Code> GetUninitialized(Isolate* isolate,
|
|
|
|
NilValue nil) {
|
2014-04-24 12:07:40 +00:00
|
|
|
return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
|
2013-04-24 11:32:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-04-24 11:32:17 +00:00
|
|
|
|
2014-02-21 11:19:32 +00:00
|
|
|
static void InstallDescriptors(Isolate* isolate) {
|
2014-04-24 06:25:42 +00:00
|
|
|
CompareNilICStub compare_stub(isolate, kNullValue, UNINITIALIZED);
|
2013-04-24 11:32:17 +00:00
|
|
|
compare_stub.InitializeInterfaceDescriptor(
|
|
|
|
isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
|
|
|
|
}
|
|
|
|
|
2013-05-16 10:59:17 +00:00
|
|
|
virtual InlineCacheState GetICState() {
|
2013-07-11 17:20:57 +00:00
|
|
|
if (state_.Contains(GENERIC)) {
|
2013-05-16 10:59:17 +00:00
|
|
|
return MEGAMORPHIC;
|
2013-06-12 17:20:37 +00:00
|
|
|
} else if (state_.Contains(MONOMORPHIC_MAP)) {
|
2013-05-16 10:59:17 +00:00
|
|
|
return MONOMORPHIC;
|
|
|
|
} else {
|
|
|
|
return PREMONOMORPHIC;
|
|
|
|
}
|
2013-04-24 11:32:17 +00:00
|
|
|
}
|
|
|
|
|
2013-05-16 10:59:17 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
|
2013-04-24 11:32:17 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-05-16 10:59:17 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const {
|
2013-07-11 17:20:57 +00:00
|
|
|
return NilValueField::encode(nil_value_) |
|
|
|
|
TypesField::encode(state_.ToIntegral());
|
2013-06-21 11:10:06 +00:00
|
|
|
}
|
2013-04-24 11:32:17 +00:00
|
|
|
|
2013-07-05 09:26:22 +00:00
|
|
|
void UpdateStatus(Handle<Object> object);
|
2013-05-16 10:59:17 +00:00
|
|
|
|
2013-06-12 17:20:37 +00:00
|
|
|
bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
|
2013-05-16 10:59:17 +00:00
|
|
|
NilValue GetNilValue() const { return nil_value_; }
|
2013-06-12 17:20:37 +00:00
|
|
|
void ClearState() { state_.RemoveAll(); }
|
2013-05-16 10:59:17 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
|
|
|
|
virtual void PrintBaseName(OStream& os) const V8_OVERRIDE; // NOLINT
|
2013-04-24 11:32:17 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
friend class CompareNilIC;
|
|
|
|
|
2013-07-11 17:20:57 +00:00
|
|
|
enum CompareNilType {
|
|
|
|
UNDEFINED,
|
|
|
|
NULL_TYPE,
|
|
|
|
MONOMORPHIC_MAP,
|
|
|
|
GENERIC,
|
|
|
|
NUMBER_OF_TYPES
|
|
|
|
};
|
|
|
|
|
|
|
|
// At most 6 different types can be distinguished, because the Code object
|
|
|
|
// only has room for a single byte to hold a set and there are two more
|
|
|
|
// boolean flags we need to store. :-P
|
|
|
|
STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
|
|
|
|
|
|
|
|
class State : public EnumSet<CompareNilType, byte> {
|
|
|
|
public:
|
|
|
|
State() : EnumSet<CompareNilType, byte>(0) { }
|
|
|
|
explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
|
|
|
|
};
|
2014-07-03 07:18:30 +00:00
|
|
|
friend OStream& operator<<(OStream& os, const State& s);
|
2013-07-11 17:20:57 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
CompareNilICStub(Isolate* isolate,
|
|
|
|
NilValue nil,
|
|
|
|
InitializationState init_state)
|
|
|
|
: HydrogenCodeStub(isolate, init_state), nil_value_(nil) { }
|
2013-04-24 11:32:17 +00:00
|
|
|
|
2013-07-11 17:20:57 +00:00
|
|
|
class NilValueField : public BitField<NilValue, 0, 1> {};
|
|
|
|
class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
|
2013-05-16 10:59:17 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual CodeStub::Major MajorKey() const { return CompareNilIC; }
|
|
|
|
virtual int NotMissMinorKey() const { return GetExtraICState(); }
|
2013-04-24 11:32:17 +00:00
|
|
|
|
2013-05-16 10:59:17 +00:00
|
|
|
NilValue nil_value_;
|
2013-06-12 17:20:37 +00:00
|
|
|
State state_;
|
2013-04-24 11:32:17 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class CEntryStub : public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
CEntryStub(Isolate* isolate,
|
|
|
|
int result_size,
|
|
|
|
SaveFPRegsMode save_doubles = kDontSaveFPRegs)
|
|
|
|
: PlatformCodeStub(isolate),
|
|
|
|
result_size_(result_size),
|
|
|
|
save_doubles_(save_doubles) { }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2011-09-15 11:30:45 +00:00
|
|
|
// The version of this stub that doesn't save doubles is generated ahead of
|
|
|
|
// time, so it's OK to call it from other stubs that can't cope with GC during
|
2011-09-16 11:29:13 +00:00
|
|
|
// their code generation. On machines that always have gp registers (x64) we
|
|
|
|
// can generate both variants ahead of time.
|
2013-02-27 12:33:24 +00:00
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
2011-09-15 11:30:45 +00:00
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
private:
|
|
|
|
// Number of pointers/values returned.
|
|
|
|
const int result_size_;
|
2011-09-19 18:36:47 +00:00
|
|
|
SaveFPRegsMode save_doubles_;
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return CEntry; }
|
|
|
|
int MinorKey() const;
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2011-03-09 10:38:19 +00:00
|
|
|
bool NeedsImmovableCode();
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class JSEntryStub : public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit JSEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void GenerateBody(MacroAssembler* masm, bool is_construct);
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return JSEntry; }
|
|
|
|
int MinorKey() const { return 0; }
|
2011-11-11 13:48:14 +00:00
|
|
|
|
|
|
|
virtual void FinishCode(Handle<Code> code);
|
|
|
|
|
|
|
|
int handler_offset_;
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class JSConstructEntryStub : public JSEntryStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit JSConstructEntryStub(Isolate* isolate) : JSEntryStub(isolate) { }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
int MinorKey() const { return 1; }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const V8_OVERRIDE { // NOLINT
|
|
|
|
os << "JSConstructEntryStub";
|
2011-07-13 11:08:25 +00:00
|
|
|
}
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class ArgumentsAccessStub: public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
|
|
|
enum Type {
|
|
|
|
READ_ELEMENT,
|
2014-03-11 14:39:08 +00:00
|
|
|
NEW_SLOPPY_FAST,
|
|
|
|
NEW_SLOPPY_SLOW,
|
2011-03-17 20:28:41 +00:00
|
|
|
NEW_STRICT
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
ArgumentsAccessStub(Isolate* isolate, Type type)
|
|
|
|
: PlatformCodeStub(isolate), type_(type) { }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Type type_;
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ArgumentsAccess; }
|
|
|
|
int MinorKey() const { return type_; }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
void GenerateReadElement(MacroAssembler* masm);
|
2011-06-16 14:12:58 +00:00
|
|
|
void GenerateNewStrict(MacroAssembler* masm);
|
2014-03-11 14:39:08 +00:00
|
|
|
void GenerateNewSloppyFast(MacroAssembler* masm);
|
|
|
|
void GenerateNewSloppySlow(MacroAssembler* masm);
|
2011-03-17 20:28:41 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class RegExpExecStub: public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return RegExpExec; }
|
|
|
|
int MinorKey() const { return 0; }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-29 13:10:35 +00:00
|
|
|
class RegExpConstructResultStub V8_FINAL : public HydrogenCodeStub {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit RegExpConstructResultStub(Isolate* isolate)
|
|
|
|
: HydrogenCodeStub(isolate) { }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2014-01-29 13:10:35 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual Major MajorKey() const V8_OVERRIDE { return RegExpConstructResult; }
|
|
|
|
virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; }
|
2014-01-29 13:10:35 +00:00
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int kLength = 0;
|
|
|
|
static const int kIndex = 1;
|
|
|
|
static const int kInput = 2;
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(RegExpConstructResultStub);
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class CallFunctionStub: public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
|
|
|
|
: PlatformCodeStub(isolate), argc_(argc), flags_(flags) { }
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2011-01-06 14:13:40 +00:00
|
|
|
static int ExtractArgcFromMinorKey(int minor_key) {
|
|
|
|
return ArgcBits::decode(minor_key);
|
|
|
|
}
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate, CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
private:
|
|
|
|
int argc_;
|
|
|
|
CallFunctionFlags flags_;
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
// Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
|
2014-01-31 16:52:17 +00:00
|
|
|
class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
|
|
|
|
class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return CallFunction; }
|
|
|
|
int MinorKey() const {
|
2010-08-30 11:48:07 +00:00
|
|
|
// Encode the parameters in a unique 32 bit value.
|
2011-09-13 12:53:28 +00:00
|
|
|
return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
|
2010-08-30 11:48:07 +00:00
|
|
|
}
|
|
|
|
|
2014-01-31 16:52:17 +00:00
|
|
|
bool CallAsMethod() {
|
|
|
|
return flags_ == CALL_AS_METHOD || flags_ == WRAP_AND_CALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NeedsChecks() {
|
|
|
|
return flags_ != WRAP_AND_CALL;
|
2011-09-27 11:42:02 +00:00
|
|
|
}
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class CallConstructStub: public PlatformCodeStub {
|
2012-01-27 13:03:19 +00:00
|
|
|
public:
|
2014-04-30 14:33:35 +00:00
|
|
|
CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
|
2014-04-24 06:25:42 +00:00
|
|
|
: PlatformCodeStub(isolate), flags_(flags) {}
|
2012-01-27 13:03:19 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2012-01-27 16:09:20 +00:00
|
|
|
virtual void FinishCode(Handle<Code> code) {
|
|
|
|
code->set_has_function_cache(RecordCallTarget());
|
|
|
|
}
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate, CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
2012-01-27 13:03:19 +00:00
|
|
|
private:
|
2014-04-30 14:33:35 +00:00
|
|
|
CallConstructorFlags flags_;
|
2012-01-27 13:03:19 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
|
2012-01-27 13:03:19 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return CallConstruct; }
|
|
|
|
int MinorKey() const { return flags_; }
|
2012-01-27 13:03:19 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
bool RecordCallTarget() const {
|
2014-04-30 14:33:35 +00:00
|
|
|
return (flags_ & RECORD_CONSTRUCTOR_TARGET) != 0;
|
2014-01-31 16:52:17 +00:00
|
|
|
}
|
2012-01-27 13:03:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
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 result,
|
|
|
|
Label* receiver_not_string,
|
|
|
|
Label* index_not_number,
|
|
|
|
Label* index_out_of_range,
|
|
|
|
StringIndexFlags index_flags)
|
|
|
|
: object_(object),
|
|
|
|
index_(index),
|
|
|
|
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(!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);
|
|
|
|
|
2013-02-20 14:29:40 +00:00
|
|
|
// Skip handling slow case and directly jump to bailout.
|
|
|
|
void SkipSlow(MacroAssembler* masm, Label* bailout) {
|
|
|
|
masm->bind(&index_not_smi_);
|
|
|
|
masm->bind(&call_runtime_);
|
|
|
|
masm->jmp(bailout);
|
|
|
|
}
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
private:
|
|
|
|
Register object_;
|
|
|
|
Register index_;
|
|
|
|
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);
|
|
|
|
|
2013-02-20 14:29:40 +00:00
|
|
|
// Skip handling slow case and directly jump to bailout.
|
|
|
|
void SkipSlow(MacroAssembler* masm, Label* bailout) {
|
|
|
|
masm->bind(&slow_case_);
|
|
|
|
masm->jmp(bailout);
|
|
|
|
}
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
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,
|
2011-11-09 14:32:51 +00:00
|
|
|
Register scratch,
|
2010-08-30 11:48:07 +00:00
|
|
|
Register result,
|
|
|
|
Label* receiver_not_string,
|
|
|
|
Label* index_not_number,
|
|
|
|
Label* index_out_of_range,
|
|
|
|
StringIndexFlags index_flags)
|
|
|
|
: char_code_at_generator_(object,
|
|
|
|
index,
|
2011-11-09 14:32:51 +00:00
|
|
|
scratch,
|
2010-08-30 11:48:07 +00:00
|
|
|
receiver_not_string,
|
|
|
|
index_not_number,
|
|
|
|
index_out_of_range,
|
|
|
|
index_flags),
|
2011-11-09 14:32:51 +00:00
|
|
|
char_from_code_generator_(scratch, result) {}
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
// Generates the fast case code. On the fallthrough path |result|
|
|
|
|
// register contains the result.
|
2013-02-20 14:29:40 +00:00
|
|
|
void GenerateFast(MacroAssembler* masm) {
|
|
|
|
char_code_at_generator_.GenerateFast(masm);
|
|
|
|
char_from_code_generator_.GenerateFast(masm);
|
|
|
|
}
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
// 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,
|
2013-02-20 14:29:40 +00:00
|
|
|
const RuntimeCallHelper& call_helper) {
|
|
|
|
char_code_at_generator_.GenerateSlow(masm, call_helper);
|
|
|
|
char_from_code_generator_.GenerateSlow(masm, call_helper);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip handling slow case and directly jump to bailout.
|
|
|
|
void SkipSlow(MacroAssembler* masm, Label* bailout) {
|
|
|
|
char_code_at_generator_.SkipSlow(masm, bailout);
|
|
|
|
char_from_code_generator_.SkipSlow(masm, bailout);
|
|
|
|
}
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
StringCharCodeAtGenerator char_code_at_generator_;
|
|
|
|
StringCharFromCodeGenerator char_from_code_generator_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
|
|
|
|
};
|
|
|
|
|
2011-01-07 10:37:26 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
class LoadDictionaryElementStub : public HydrogenCodeStub {
|
2011-05-18 13:17:29 +00:00
|
|
|
public:
|
2014-07-29 16:07:34 +00:00
|
|
|
explicit LoadDictionaryElementStub(Isolate* isolate)
|
2014-04-24 06:25:42 +00:00
|
|
|
: HydrogenCodeStub(isolate) {}
|
2011-05-18 13:17:29 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-11-15 17:53:35 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
|
|
|
private:
|
2014-07-29 16:07:34 +00:00
|
|
|
Major MajorKey() const { return LoadElement; }
|
2014-07-03 07:18:30 +00:00
|
|
|
int NotMissMinorKey() const { return DICTIONARY_ELEMENTS; }
|
2013-11-15 17:53:35 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(LoadDictionaryElementStub);
|
2013-11-15 17:53:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
class LoadDictionaryElementPlatformStub : public PlatformCodeStub {
|
2013-11-15 17:53:35 +00:00
|
|
|
public:
|
2014-07-29 16:07:34 +00:00
|
|
|
explicit LoadDictionaryElementPlatformStub(Isolate* isolate)
|
2014-04-24 06:25:42 +00:00
|
|
|
: PlatformCodeStub(isolate) {}
|
2013-11-15 17:53:35 +00:00
|
|
|
|
2011-05-18 13:17:29 +00:00
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2011-07-08 10:46:10 +00:00
|
|
|
private:
|
2014-07-29 16:07:34 +00:00
|
|
|
Major MajorKey() const { return LoadElement; }
|
2014-07-03 07:18:30 +00:00
|
|
|
int MinorKey() const { return DICTIONARY_ELEMENTS; }
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(LoadDictionaryElementPlatformStub);
|
2012-12-18 16:25:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
class KeyedLoadGenericStub : public HydrogenCodeStub {
|
2014-06-12 09:58:10 +00:00
|
|
|
public:
|
2014-07-29 16:07:34 +00:00
|
|
|
explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
|
2014-06-12 09:58:10 +00:00
|
|
|
|
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
|
|
|
|
virtual InlineCacheState GetICState() { return GENERIC; }
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return KeyedLoadGeneric; }
|
|
|
|
int NotMissMinorKey() const { return 0; }
|
2014-06-12 09:58:10 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(KeyedLoadGenericStub);
|
2014-06-12 09:58:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-07-12 12:28:32 +00:00
|
|
|
class DoubleToIStub : public PlatformCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
DoubleToIStub(Isolate* isolate,
|
|
|
|
Register source,
|
2013-07-12 12:28:32 +00:00
|
|
|
Register destination,
|
|
|
|
int offset,
|
2013-08-26 12:24:03 +00:00
|
|
|
bool is_truncating,
|
2014-04-24 06:25:42 +00:00
|
|
|
bool skip_fastpath = false)
|
|
|
|
: PlatformCodeStub(isolate), bit_field_(0) {
|
2014-02-12 09:19:30 +00:00
|
|
|
bit_field_ = SourceRegisterBits::encode(source.code()) |
|
|
|
|
DestinationRegisterBits::encode(destination.code()) |
|
2013-07-12 12:28:32 +00:00
|
|
|
OffsetBits::encode(offset) |
|
2013-08-26 12:24:03 +00:00
|
|
|
IsTruncatingBits::encode(is_truncating) |
|
2013-10-04 08:17:11 +00:00
|
|
|
SkipFastPathBits::encode(skip_fastpath) |
|
2014-05-16 15:18:24 +00:00
|
|
|
SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
|
2013-07-12 12:28:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Register source() {
|
2014-02-12 09:19:30 +00:00
|
|
|
return Register::from_code(SourceRegisterBits::decode(bit_field_));
|
2013-07-12 12:28:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Register destination() {
|
2014-02-12 09:19:30 +00:00
|
|
|
return Register::from_code(DestinationRegisterBits::decode(bit_field_));
|
2013-07-12 12:28:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool is_truncating() {
|
|
|
|
return IsTruncatingBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2013-08-26 12:24:03 +00:00
|
|
|
bool skip_fastpath() {
|
|
|
|
return SkipFastPathBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2013-07-12 12:28:32 +00:00
|
|
|
int offset() {
|
|
|
|
return OffsetBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2013-08-26 12:24:03 +00:00
|
|
|
virtual bool SometimesSetsUpAFrame() { return false; }
|
|
|
|
|
2013-07-12 12:28:32 +00:00
|
|
|
private:
|
|
|
|
static const int kBitsPerRegisterNumber = 6;
|
|
|
|
STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
|
|
|
|
class SourceRegisterBits:
|
|
|
|
public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
|
|
|
|
class DestinationRegisterBits:
|
|
|
|
public BitField<int, kBitsPerRegisterNumber,
|
|
|
|
kBitsPerRegisterNumber> {}; // NOLINT
|
|
|
|
class IsTruncatingBits:
|
|
|
|
public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
|
|
|
|
class OffsetBits:
|
|
|
|
public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
|
2013-08-26 12:24:03 +00:00
|
|
|
class SkipFastPathBits:
|
|
|
|
public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
|
2014-05-09 13:01:50 +00:00
|
|
|
class SSE3Bits:
|
|
|
|
public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
|
2013-07-12 12:28:32 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return DoubleToI; }
|
|
|
|
int MinorKey() const { return bit_field_; }
|
2013-07-12 12:28:32 +00:00
|
|
|
|
|
|
|
int bit_field_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
class LoadFastElementStub : public HydrogenCodeStub {
|
2012-12-18 16:25:45 +00:00
|
|
|
public:
|
2014-07-29 16:07:34 +00:00
|
|
|
LoadFastElementStub(Isolate* isolate, bool is_js_array,
|
|
|
|
ElementsKind elements_kind)
|
2014-04-24 06:25:42 +00:00
|
|
|
: HydrogenCodeStub(isolate) {
|
2012-12-18 16:25:45 +00:00
|
|
|
bit_field_ = ElementsKindBits::encode(elements_kind) |
|
|
|
|
IsJSArrayBits::encode(is_js_array);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_js_array() const {
|
|
|
|
return IsJSArrayBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind elements_kind() const {
|
|
|
|
return ElementsKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2012-12-18 16:25:45 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2012-12-18 16:25:45 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
|
2013-04-18 20:37:27 +00:00
|
|
|
class IsJSArrayBits: public BitField<bool, 8, 1> {};
|
2012-12-18 16:25:45 +00:00
|
|
|
uint32_t bit_field_;
|
2011-07-08 10:46:10 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
Major MajorKey() const { return LoadElement; }
|
2014-07-03 07:18:30 +00:00
|
|
|
int NotMissMinorKey() const { return bit_field_; }
|
2013-02-26 13:08:08 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(LoadFastElementStub);
|
2011-05-18 13:17:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
class StoreFastElementStub : public HydrogenCodeStub {
|
2013-03-20 10:37:13 +00:00
|
|
|
public:
|
2014-07-29 16:07:34 +00:00
|
|
|
StoreFastElementStub(Isolate* isolate, bool is_js_array,
|
|
|
|
ElementsKind elements_kind, KeyedAccessStoreMode mode)
|
2014-04-24 06:25:42 +00:00
|
|
|
: HydrogenCodeStub(isolate) {
|
2013-03-20 10:37:13 +00:00
|
|
|
bit_field_ = ElementsKindBits::encode(elements_kind) |
|
|
|
|
IsJSArrayBits::encode(is_js_array) |
|
|
|
|
StoreModeBits::encode(mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_js_array() const {
|
|
|
|
return IsJSArrayBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind elements_kind() const {
|
|
|
|
return ElementsKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
KeyedAccessStoreMode store_mode() const {
|
|
|
|
return StoreModeBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-03-20 10:37:13 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-03-20 10:37:13 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
|
|
|
|
class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
|
|
|
|
class IsJSArrayBits: public BitField<bool, 12, 1> {};
|
|
|
|
uint32_t bit_field_;
|
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
Major MajorKey() const { return StoreElement; }
|
2014-07-03 07:18:30 +00:00
|
|
|
int NotMissMinorKey() const { return bit_field_; }
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(StoreFastElementStub);
|
2013-03-20 10:37:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-04 12:01:59 +00:00
|
|
|
class TransitionElementsKindStub : public HydrogenCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
TransitionElementsKindStub(Isolate* isolate,
|
|
|
|
ElementsKind from_kind,
|
2014-03-18 13:29:29 +00:00
|
|
|
ElementsKind to_kind,
|
2014-04-24 06:25:42 +00:00
|
|
|
bool is_js_array) : HydrogenCodeStub(isolate) {
|
2013-02-04 12:01:59 +00:00
|
|
|
bit_field_ = FromKindBits::encode(from_kind) |
|
2014-03-18 13:29:29 +00:00
|
|
|
ToKindBits::encode(to_kind) |
|
|
|
|
IsJSArrayBits::encode(is_js_array);
|
2013-02-04 12:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind from_kind() const {
|
|
|
|
return FromKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind to_kind() const {
|
|
|
|
return ToKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2014-03-18 13:29:29 +00:00
|
|
|
bool is_js_array() const {
|
|
|
|
return IsJSArrayBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-02-04 12:01:59 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-02-04 12:01:59 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
class FromKindBits: public BitField<ElementsKind, 8, 8> {};
|
|
|
|
class ToKindBits: public BitField<ElementsKind, 0, 8> {};
|
2014-03-18 13:29:29 +00:00
|
|
|
class IsJSArrayBits: public BitField<bool, 16, 1> {};
|
2013-02-04 12:01:59 +00:00
|
|
|
uint32_t bit_field_;
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return TransitionElementsKind; }
|
|
|
|
int NotMissMinorKey() const { return bit_field_; }
|
2013-02-26 13:08:08 +00:00
|
|
|
|
2013-02-04 12:01:59 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
class ArrayConstructorStubBase : public HydrogenCodeStub {
|
2013-03-01 16:06:34 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
ArrayConstructorStubBase(Isolate* isolate,
|
|
|
|
ElementsKind kind,
|
|
|
|
AllocationSiteOverrideMode override_mode)
|
|
|
|
: HydrogenCodeStub(isolate) {
|
2013-06-04 12:48:51 +00:00
|
|
|
// It only makes sense to override local allocation site behavior
|
|
|
|
// if there is a difference between the global allocation site policy
|
|
|
|
// for an ElementsKind and the desired usage of the stub.
|
2014-01-07 15:58:25 +00:00
|
|
|
ASSERT(override_mode != DISABLE_ALLOCATION_SITES ||
|
2013-07-08 10:02:16 +00:00
|
|
|
AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
|
2013-04-25 16:00:32 +00:00
|
|
|
bit_field_ = ElementsKindBits::encode(kind) |
|
2014-01-09 15:07:23 +00:00
|
|
|
AllocationSiteOverrideModeBits::encode(override_mode);
|
2013-04-25 16:00:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind elements_kind() const {
|
|
|
|
return ElementsKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode() const {
|
|
|
|
return AllocationSiteOverrideModeBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
static void GenerateStubsAheadOfTime(Isolate* isolate);
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
2013-05-07 21:01:53 +00:00
|
|
|
static const int kConstructor = 0;
|
2014-01-21 16:04:39 +00:00
|
|
|
static const int kAllocationSite = 1;
|
2013-04-25 16:00:32 +00:00
|
|
|
|
2013-12-18 22:51:23 +00:00
|
|
|
protected:
|
2014-07-03 07:18:30 +00:00
|
|
|
OStream& BasePrintName(OStream& os, const char* name) const; // NOLINT
|
2013-12-18 22:51:23 +00:00
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
int NotMissMinorKey() const { return bit_field_; }
|
2013-04-25 16:00:32 +00:00
|
|
|
|
2013-06-28 13:16:14 +00:00
|
|
|
// Ensure data fits within available bits.
|
|
|
|
STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
|
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
|
2013-06-28 13:16:14 +00:00
|
|
|
class AllocationSiteOverrideModeBits: public
|
|
|
|
BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
|
2013-04-25 16:00:32 +00:00
|
|
|
uint32_t bit_field_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
|
|
|
|
public:
|
|
|
|
ArrayNoArgumentConstructorStub(
|
2014-04-24 06:25:42 +00:00
|
|
|
Isolate* isolate,
|
2013-04-25 16:00:32 +00:00
|
|
|
ElementsKind kind,
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
|
2014-04-24 06:25:42 +00:00
|
|
|
: ArrayConstructorStubBase(isolate, kind, override_mode) {
|
2013-03-01 16:06:34 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ArrayNoArgumentConstructor; }
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const V8_OVERRIDE { // NOLINT
|
|
|
|
BasePrintName(os, "ArrayNoArgumentConstructorStub");
|
2013-12-18 22:51:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 16:06:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
|
2013-03-01 16:06:34 +00:00
|
|
|
public:
|
2013-04-25 16:00:32 +00:00
|
|
|
ArraySingleArgumentConstructorStub(
|
2014-04-24 06:25:42 +00:00
|
|
|
Isolate* isolate,
|
2013-04-25 16:00:32 +00:00
|
|
|
ElementsKind kind,
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
|
2014-04-24 06:25:42 +00:00
|
|
|
: ArrayConstructorStubBase(isolate, kind, override_mode) {
|
2013-04-25 16:00:32 +00:00
|
|
|
}
|
2013-03-01 16:06:34 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ArraySingleArgumentConstructor; }
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const { // NOLINT
|
|
|
|
BasePrintName(os, "ArraySingleArgumentConstructorStub");
|
2013-12-18 22:51:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 16:06:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
|
2013-03-01 16:06:34 +00:00
|
|
|
public:
|
2013-04-25 16:00:32 +00:00
|
|
|
ArrayNArgumentsConstructorStub(
|
2014-04-24 06:25:42 +00:00
|
|
|
Isolate* isolate,
|
2013-04-25 16:00:32 +00:00
|
|
|
ElementsKind kind,
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
|
2014-04-24 06:25:42 +00:00
|
|
|
: ArrayConstructorStubBase(isolate, kind, override_mode) {
|
2013-04-25 16:00:32 +00:00
|
|
|
}
|
2013-03-01 16:06:34 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ArrayNArgumentsConstructor; }
|
2013-04-18 20:37:27 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintName(OStream& os) const { // NOLINT
|
|
|
|
BasePrintName(os, "ArrayNArgumentsConstructorStub");
|
2013-12-18 22:51:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 16:06:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-06-05 10:43:18 +00:00
|
|
|
class InternalArrayConstructorStubBase : public HydrogenCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
|
|
|
|
: HydrogenCodeStub(isolate) {
|
2013-06-05 10:43:18 +00:00
|
|
|
kind_ = kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GenerateStubsAheadOfTime(Isolate* isolate);
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int kConstructor = 0;
|
|
|
|
|
|
|
|
ElementsKind elements_kind() const { return kind_; }
|
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
int NotMissMinorKey() const { return kind_; }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
ElementsKind kind_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class InternalArrayNoArgumentConstructorStub : public
|
|
|
|
InternalArrayConstructorStubBase {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
InternalArrayNoArgumentConstructorStub(Isolate* isolate,
|
|
|
|
ElementsKind kind)
|
|
|
|
: InternalArrayConstructorStubBase(isolate, kind) { }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return InternalArrayNoArgumentConstructor; }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class InternalArraySingleArgumentConstructorStub : public
|
|
|
|
InternalArrayConstructorStubBase {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
InternalArraySingleArgumentConstructorStub(Isolate* isolate,
|
|
|
|
ElementsKind kind)
|
|
|
|
: InternalArrayConstructorStubBase(isolate, kind) { }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return InternalArraySingleArgumentConstructor; }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class InternalArrayNArgumentsConstructorStub : public
|
|
|
|
InternalArrayConstructorStubBase {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
|
|
|
|
: InternalArrayConstructorStubBase(isolate, kind) { }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return InternalArrayNArgumentsConstructor; }
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
class StoreElementStub : public PlatformCodeStub {
|
2011-05-18 13:17:29 +00:00
|
|
|
public:
|
2014-07-29 16:07:34 +00:00
|
|
|
StoreElementStub(Isolate* isolate, bool is_js_array,
|
|
|
|
ElementsKind elements_kind, KeyedAccessStoreMode store_mode)
|
2014-04-24 06:25:42 +00:00
|
|
|
: PlatformCodeStub(isolate),
|
|
|
|
is_js_array_(is_js_array),
|
2012-02-10 12:36:05 +00:00
|
|
|
elements_kind_(elements_kind),
|
2014-07-29 16:07:34 +00:00
|
|
|
store_mode_(store_mode) {}
|
2011-05-18 13:17:29 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
Major MajorKey() const { return StoreElement; }
|
2014-07-03 07:18:30 +00:00
|
|
|
int MinorKey() const {
|
2012-02-10 12:36:05 +00:00
|
|
|
return ElementsKindBits::encode(elements_kind_) |
|
|
|
|
IsJSArrayBits::encode(is_js_array_) |
|
2014-05-09 13:01:50 +00:00
|
|
|
StoreModeBits::encode(store_mode_);
|
2011-07-08 10:46:10 +00:00
|
|
|
}
|
2011-05-18 13:17:29 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2011-07-08 10:46:10 +00:00
|
|
|
private:
|
2013-03-06 21:51:07 +00:00
|
|
|
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
|
|
|
|
class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
|
|
|
|
class IsJSArrayBits: public BitField<bool, 12, 1> {};
|
2012-02-10 12:36:05 +00:00
|
|
|
|
2011-07-08 10:46:10 +00:00
|
|
|
bool is_js_array_;
|
2011-09-09 09:35:57 +00:00
|
|
|
ElementsKind elements_kind_;
|
2013-03-06 21:51:07 +00:00
|
|
|
KeyedAccessStoreMode store_mode_;
|
2011-07-08 10:46:10 +00:00
|
|
|
|
2014-07-29 16:07:34 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(StoreElementStub);
|
2011-05-18 13:17:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-29 14:49:28 +00:00
|
|
|
class ToBooleanStub: public HydrogenCodeStub {
|
2011-06-22 08:28:35 +00:00
|
|
|
public:
|
2011-07-21 13:51:04 +00:00
|
|
|
enum Type {
|
|
|
|
UNDEFINED,
|
|
|
|
BOOLEAN,
|
|
|
|
NULL_TYPE,
|
|
|
|
SMI,
|
|
|
|
SPEC_OBJECT,
|
|
|
|
STRING,
|
2013-03-22 16:33:50 +00:00
|
|
|
SYMBOL,
|
2011-07-21 13:51:04 +00:00
|
|
|
HEAP_NUMBER,
|
|
|
|
NUMBER_OF_TYPES
|
|
|
|
};
|
|
|
|
|
2011-07-22 12:42:40 +00:00
|
|
|
// At most 8 different types can be distinguished, because the Code object
|
|
|
|
// only has room for a single byte to hold a set of these types. :-P
|
|
|
|
STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
|
|
|
|
|
2013-05-16 10:59:17 +00:00
|
|
|
class Types : public EnumSet<Type, byte> {
|
2011-07-21 13:51:04 +00:00
|
|
|
public:
|
2013-06-20 13:51:03 +00:00
|
|
|
Types() : EnumSet<Type, byte>(0) {}
|
2013-05-16 10:59:17 +00:00
|
|
|
explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
|
2011-07-21 13:51:04 +00:00
|
|
|
|
2013-05-16 10:59:17 +00:00
|
|
|
byte ToByte() const { return ToIntegral(); }
|
2013-07-05 09:26:22 +00:00
|
|
|
bool UpdateStatus(Handle<Object> object);
|
2011-07-28 13:33:51 +00:00
|
|
|
bool NeedsMap() const;
|
2011-08-11 07:22:16 +00:00
|
|
|
bool CanBeUndetectable() const;
|
2013-06-20 13:51:03 +00:00
|
|
|
bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
|
2011-07-21 13:51:04 +00:00
|
|
|
|
2013-06-20 13:51:03 +00:00
|
|
|
static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
|
|
|
|
};
|
2011-07-25 14:08:36 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
ToBooleanStub(Isolate* isolate, Types types = Types())
|
|
|
|
: HydrogenCodeStub(isolate), types_(types) { }
|
|
|
|
ToBooleanStub(Isolate* isolate, ExtraICState state)
|
|
|
|
: HydrogenCodeStub(isolate), types_(static_cast<byte>(state)) { }
|
2013-05-29 14:49:28 +00:00
|
|
|
|
2013-07-05 09:26:22 +00:00
|
|
|
bool UpdateStatus(Handle<Object> object);
|
2013-05-29 14:49:28 +00:00
|
|
|
Types GetTypes() { return types_; }
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-05-29 14:49:28 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
2014-04-24 12:07:40 +00:00
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2011-06-22 08:28:35 +00:00
|
|
|
|
2013-04-18 09:50:46 +00:00
|
|
|
virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
|
2011-06-22 08:28:35 +00:00
|
|
|
|
2011-09-15 11:30:45 +00:00
|
|
|
virtual bool SometimesSetsUpAFrame() { return false; }
|
|
|
|
|
2014-02-21 11:19:32 +00:00
|
|
|
static void InstallDescriptors(Isolate* isolate) {
|
2014-04-24 06:25:42 +00:00
|
|
|
ToBooleanStub stub(isolate);
|
2013-05-29 14:49:28 +00:00
|
|
|
stub.InitializeInterfaceDescriptor(
|
|
|
|
isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
|
|
|
|
}
|
2011-07-22 12:42:40 +00:00
|
|
|
|
2013-05-29 14:49:28 +00:00
|
|
|
static Handle<Code> GetUninitialized(Isolate* isolate) {
|
2014-04-24 12:07:40 +00:00
|
|
|
return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
|
2011-07-22 12:42:40 +00:00
|
|
|
}
|
2011-07-21 13:51:04 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
virtual ExtraICState GetExtraICState() const { return types_.ToIntegral(); }
|
2013-05-29 14:49:28 +00:00
|
|
|
|
2013-06-07 13:11:17 +00:00
|
|
|
virtual InlineCacheState GetICState() {
|
|
|
|
if (types_.IsEmpty()) {
|
|
|
|
return ::v8::internal::UNINITIALIZED;
|
|
|
|
} else {
|
|
|
|
return MONOMORPHIC;
|
|
|
|
}
|
|
|
|
}
|
2013-05-29 14:49:28 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ToBoolean; }
|
|
|
|
int NotMissMinorKey() const { return GetExtraICState(); }
|
2013-05-29 14:49:28 +00:00
|
|
|
|
2014-04-24 06:25:42 +00:00
|
|
|
ToBooleanStub(Isolate* isolate, InitializationState init_state) :
|
|
|
|
HydrogenCodeStub(isolate, init_state) {}
|
2011-07-21 13:51:04 +00:00
|
|
|
|
|
|
|
Types types_;
|
2011-06-22 08:28:35 +00:00
|
|
|
};
|
|
|
|
|
2011-10-13 10:53:31 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
|
|
|
|
|
|
|
|
|
2013-07-17 11:37:20 +00:00
|
|
|
class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
|
2011-10-13 10:53:31 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
ElementsTransitionAndStoreStub(Isolate* isolate,
|
|
|
|
ElementsKind from_kind,
|
2013-07-17 11:37:20 +00:00
|
|
|
ElementsKind to_kind,
|
2011-10-20 12:36:45 +00:00
|
|
|
bool is_jsarray,
|
2013-03-06 21:51:07 +00:00
|
|
|
KeyedAccessStoreMode store_mode)
|
2014-04-24 06:25:42 +00:00
|
|
|
: HydrogenCodeStub(isolate),
|
|
|
|
from_kind_(from_kind),
|
2013-07-17 11:37:20 +00:00
|
|
|
to_kind_(to_kind),
|
|
|
|
is_jsarray_(is_jsarray),
|
|
|
|
store_mode_(store_mode) {}
|
|
|
|
|
|
|
|
ElementsKind from_kind() const { return from_kind_; }
|
|
|
|
ElementsKind to_kind() const { return to_kind_; }
|
|
|
|
bool is_jsarray() const { return is_jsarray_; }
|
|
|
|
KeyedAccessStoreMode store_mode() const { return store_mode_; }
|
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
2013-07-17 11:37:20 +00:00
|
|
|
|
2014-04-24 12:07:40 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
2013-07-17 11:37:20 +00:00
|
|
|
|
2014-07-15 10:19:30 +00:00
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
enum ParameterIndices {
|
2014-07-14 20:43:41 +00:00
|
|
|
kValueIndex,
|
|
|
|
kMapIndex,
|
|
|
|
kKeyIndex,
|
|
|
|
kObjectIndex,
|
2014-07-15 10:19:30 +00:00
|
|
|
kParameterCount
|
2014-07-14 20:43:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const Register ValueRegister() {
|
|
|
|
return KeyedStoreIC::ValueRegister();
|
|
|
|
}
|
|
|
|
static const Register MapRegister() { return KeyedStoreIC::MapRegister(); }
|
|
|
|
static const Register KeyRegister() { return KeyedStoreIC::NameRegister(); }
|
|
|
|
static const Register ObjectRegister() {
|
|
|
|
return KeyedStoreIC::ReceiverRegister();
|
|
|
|
}
|
|
|
|
|
2013-07-17 11:37:20 +00:00
|
|
|
private:
|
|
|
|
class FromBits: public BitField<ElementsKind, 0, 8> {};
|
|
|
|
class ToBits: public BitField<ElementsKind, 8, 8> {};
|
|
|
|
class IsJSArrayBits: public BitField<bool, 16, 1> {};
|
|
|
|
class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
|
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ElementsTransitionAndStore; }
|
|
|
|
int NotMissMinorKey() const {
|
2013-07-17 11:37:20 +00:00
|
|
|
return FromBits::encode(from_kind_) |
|
|
|
|
ToBits::encode(to_kind_) |
|
|
|
|
IsJSArrayBits::encode(is_jsarray_) |
|
|
|
|
StoreModeBits::encode(store_mode_);
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind from_kind_;
|
|
|
|
ElementsKind to_kind_;
|
|
|
|
bool is_jsarray_;
|
|
|
|
KeyedAccessStoreMode store_mode_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class StoreArrayLiteralElementStub : public PlatformCodeStub {
|
2011-10-31 14:42:06 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit StoreArrayLiteralElementStub(Isolate* isolate)
|
2014-05-09 13:01:50 +00:00
|
|
|
: PlatformCodeStub(isolate) { }
|
2011-10-31 14:42:06 +00:00
|
|
|
|
|
|
|
private:
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return StoreArrayLiteralElement; }
|
|
|
|
int MinorKey() const { return 0; }
|
2011-10-31 14:42:06 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
|
|
|
|
};
|
|
|
|
|
2012-07-17 15:18:15 +00:00
|
|
|
|
2013-01-29 09:12:20 +00:00
|
|
|
class StubFailureTrampolineStub : public PlatformCodeStub {
|
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
|
|
|
|
: PlatformCodeStub(isolate),
|
|
|
|
function_mode_(function_mode) {}
|
2013-02-05 08:09:32 +00:00
|
|
|
|
2013-02-27 12:33:24 +00:00
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
2013-01-29 09:12:20 +00:00
|
|
|
|
|
|
|
private:
|
2014-05-09 13:01:50 +00:00
|
|
|
class FunctionModeField: public BitField<StubFunctionMode, 0, 1> {};
|
2013-04-04 17:55:43 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return StubFailureTrampoline; }
|
|
|
|
int MinorKey() const { return FunctionModeField::encode(function_mode_); }
|
2013-01-29 09:12:20 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2013-04-02 11:28:01 +00:00
|
|
|
StubFunctionMode function_mode_;
|
2013-02-05 08:09:32 +00:00
|
|
|
|
2013-01-29 09:12:20 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class ProfileEntryHookStub : public PlatformCodeStub {
|
2012-07-17 15:18:15 +00:00
|
|
|
public:
|
2014-04-24 06:25:42 +00:00
|
|
|
explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
2012-07-17 15:18:15 +00:00
|
|
|
|
|
|
|
// The profile entry hook function is not allowed to cause a GC.
|
|
|
|
virtual bool SometimesSetsUpAFrame() { return false; }
|
|
|
|
|
|
|
|
// Generates a call to the entry hook if it's enabled.
|
|
|
|
static void MaybeCallEntryHook(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
|
|
|
static void EntryHookTrampoline(intptr_t function,
|
2013-09-11 06:56:47 +00:00
|
|
|
intptr_t stack_pointer,
|
|
|
|
Isolate* isolate);
|
2012-07-17 15:18:15 +00:00
|
|
|
|
2014-07-03 07:18:30 +00:00
|
|
|
Major MajorKey() const { return ProfileEntryHook; }
|
|
|
|
int MinorKey() const { return 0; }
|
2012-07-17 15:18:15 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
|
|
|
|
};
|
|
|
|
|
This is a preview of a first step towards unification of the hydrogen
call machinery. The change replaces CallNamed, CallKeyed,
CallConstantFunction and CallKnownGlobal hydrogen instructions with two
new instructions with a more lower level semantics:
1. CallJSFunction for direct calls of JSFunction objects (no
argument adaptation)
2. CallWithDescriptor for calls of a given Code object according to
the supplied calling convention.
Details:
CallJSFunction should be straightforward, the main difference from the
existing InvokeFunction instruction is the absence of argument adaptor
handling. (As a next step, we will replace InvokeFunction with an
equivalent hydrogen code.)
For CallWithDescriptor, the calling conventions are represented by a
tweaked version of CallStubInterfaceDescriptor. In addition to the
parameter-register mapping, we also define parameter-representation
mapping there. The CallWithDescriptor instruction has variable number of
parameters now - this required some simple tweaks in Lithium, which
assumed fixed number of arguments in some places.
The calling conventions used in the calls are initialized in the
CallDescriptors class (code-stubs.h, <arch>/code-stubs-<arch>.cc), and
they live in a new table in the Isolate class. I should say I am not
quite sure about Representation::Integer32() representation for some of
the params of ArgumentAdaptorCall - it is not clear to me wether the
params could not end up on the stack and thus confuse the GC.
The change also includes an earlier small change to argument adaptor
(https://codereview.chromium.org/98463007) that avoids passing a naked
pointer to the code entry as a parameter. I am sorry for packaging that
with an already biggish change.
Performance implications:
Locally, I see a small regression (.2% or so). It is hard to say where
exactly it comes from, but I do see inefficient call sequences to the
adaptor trampoline. For example:
;;; <@78,#24> constant-t
bf85aa515a mov edi,0x5a51aa85 ;; debug: position 29
;;; <@72,#53> load-named-field
8b7717 mov esi,[edi+0x17] ;; debug: position 195
;;; <@80,#51> constant-s
b902000000 mov ecx,0x2 ;; debug: position 195
;;; <@81,#51> gap
894df0 mov [ebp+0xf0],ecx
;;; <@82,#103> constant-i
bb01000000 mov ebx,0x1
;;; <@84,#102> constant-i
b902000000 mov ecx,0x2
;;; <@85,#102> gap
89d8 mov eax,ebx
89cb mov ebx,ecx
8b4df0 mov ecx,[ebp+0xf0]
;;; <@86,#58> call-with-descriptor
e8ef57fcff call ArgumentsAdaptorTrampoline (0x2d80e6e0) ;; code: BUILTIN
Note the silly handling of ecx; the hydrogen for this code is:
0 4 s27 Constant 1 range:1_1 <|@
0 3 t30 Constant 0x5bc1aa85 <JS Function xyz (SharedFunctionInfo 0x5bc1a919)> type:object <|@
0 1 t36 LoadNamedField t30.[in-object]@24 <|@
0 1 t38 Constant 0x2300e6a1 <Code> <|@
0 1 i102 Constant 2 range:2_2 <|@
0 1 i103 Constant 1 range:1_1 <|@
0 2 t41 CallWithDescriptor t38 t30 t36 s27 i103 i102 #2 changes[*] <|@
BUG=
R=verwaest@chromium.org, danno@chromium.org
Review URL: https://codereview.chromium.org/104663004
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18626 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-15 17:00:35 +00:00
|
|
|
|
|
|
|
class CallDescriptors {
|
|
|
|
public:
|
|
|
|
static void InitializeForIsolate(Isolate* isolate);
|
|
|
|
};
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_CODE_STUBS_H_
|