2012-02-10 08:47:35 +00:00
|
|
|
// Copyright 2012 the V8 project authors. All rights reserved.
|
2008-07-03 15:10:15 +00:00
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above
|
|
|
|
// copyright notice, this list of conditions and the following
|
|
|
|
// disclaimer in the documentation and/or other materials provided
|
|
|
|
// with the distribution.
|
|
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
|
|
// contributors may be used to endorse or promote products derived
|
|
|
|
// from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
#ifndef V8_CODE_STUBS_H_
|
|
|
|
#define V8_CODE_STUBS_H_
|
|
|
|
|
2011-05-06 06:50:20 +00:00
|
|
|
#include "allocation.h"
|
2013-04-18 20:37:27 +00:00
|
|
|
#include "assembler.h"
|
2011-10-20 12:36:45 +00:00
|
|
|
#include "codegen.h"
|
2013-10-18 14:55:21 +00:00
|
|
|
#include "globals.h"
|
|
|
|
#include "macro-assembler.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.
|
2009-11-11 14:32:14 +00:00
|
|
|
#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
|
|
|
|
V(CallFunction) \
|
2012-01-27 13:03:19 +00:00
|
|
|
V(CallConstruct) \
|
2013-12-02 13:14:07 +00:00
|
|
|
V(BinaryOpIC) \
|
2014-01-02 15:31:27 +00:00
|
|
|
V(BinaryOpICWithAllocationSite) \
|
|
|
|
V(BinaryOpWithAllocationSite) \
|
2009-12-03 07:56:21 +00:00
|
|
|
V(StringAdd) \
|
2010-01-07 09:59:37 +00:00
|
|
|
V(SubString) \
|
2010-01-08 11:58:15 +00:00
|
|
|
V(StringCompare) \
|
2009-11-11 14:32:14 +00:00
|
|
|
V(Compare) \
|
2011-05-25 12:40:04 +00:00
|
|
|
V(CompareIC) \
|
2013-04-24 11:32:17 +00:00
|
|
|
V(CompareNilIC) \
|
2010-12-07 11:31:57 +00:00
|
|
|
V(MathPow) \
|
2013-01-21 14:53:29 +00:00
|
|
|
V(StringLength) \
|
2013-01-21 17:54:36 +00:00
|
|
|
V(FunctionPrototype) \
|
2013-01-25 11:55:29 +00:00
|
|
|
V(StoreArrayLength) \
|
2011-09-19 18:36:47 +00:00
|
|
|
V(RecordWrite) \
|
|
|
|
V(StoreBufferOverflow) \
|
|
|
|
V(RegExpExec) \
|
2011-01-07 10:37:26 +00:00
|
|
|
V(Instanceof) \
|
2009-11-11 14:32:14 +00:00
|
|
|
V(ConvertToDouble) \
|
|
|
|
V(WriteInt32ToHeapNumber) \
|
|
|
|
V(StackCheck) \
|
2012-02-14 14:00:31 +00:00
|
|
|
V(Interrupt) \
|
2009-12-16 15:43:20 +00:00
|
|
|
V(FastNewClosure) \
|
2009-12-17 08:53:19 +00:00
|
|
|
V(FastNewContext) \
|
2011-10-06 15:59:02 +00:00
|
|
|
V(FastNewBlockContext) \
|
2009-12-17 15:35:15 +00:00
|
|
|
V(FastCloneShallowArray) \
|
2011-11-21 13:27:44 +00:00
|
|
|
V(FastCloneShallowObject) \
|
2013-07-08 10:02:16 +00:00
|
|
|
V(CreateAllocationSite) \
|
2009-11-11 14:32:14 +00:00
|
|
|
V(ToBoolean) \
|
2011-01-28 14:18:26 +00:00
|
|
|
V(ToNumber) \
|
2009-11-11 14:32:14 +00:00
|
|
|
V(ArgumentsAccess) \
|
2010-12-07 11:31:57 +00:00
|
|
|
V(RegExpConstructResult) \
|
2010-02-16 09:41:11 +00:00
|
|
|
V(NumberToString) \
|
2013-07-12 12:28:32 +00:00
|
|
|
V(DoubleToI) \
|
2009-11-11 14:32:14 +00:00
|
|
|
V(CEntry) \
|
2010-01-29 12:41:11 +00:00
|
|
|
V(JSEntry) \
|
2011-07-08 10:46:10 +00:00
|
|
|
V(KeyedLoadElement) \
|
2014-01-20 17:09:24 +00:00
|
|
|
V(ArrayPush) \
|
2013-03-01 16:06:34 +00:00
|
|
|
V(ArrayNoArgumentConstructor) \
|
|
|
|
V(ArraySingleArgumentConstructor) \
|
|
|
|
V(ArrayNArgumentsConstructor) \
|
2013-06-05 10:43:18 +00:00
|
|
|
V(InternalArrayNoArgumentConstructor) \
|
|
|
|
V(InternalArraySingleArgumentConstructor) \
|
|
|
|
V(InternalArrayNArgumentsConstructor) \
|
2011-07-08 10:46:10 +00:00
|
|
|
V(KeyedStoreElement) \
|
2011-05-05 12:30:57 +00:00
|
|
|
V(DebuggerStatement) \
|
2013-03-04 15:00:57 +00:00
|
|
|
V(NameDictionaryLookup) \
|
2011-10-31 14:42:06 +00:00
|
|
|
V(ElementsTransitionAndStore) \
|
2013-02-04 12:01:59 +00:00
|
|
|
V(TransitionElementsKind) \
|
2012-07-17 15:18:15 +00:00
|
|
|
V(StoreArrayLiteralElement) \
|
2013-01-29 09:12:20 +00:00
|
|
|
V(StubFailureTrampoline) \
|
2013-11-15 10:52:05 +00:00
|
|
|
V(StubFailureTailCallTrampoline) \
|
2013-04-25 16:00:32 +00:00
|
|
|
V(ArrayConstructor) \
|
2013-06-05 10:43:18 +00:00
|
|
|
V(InternalArrayConstructor) \
|
2013-03-04 14:03:27 +00:00
|
|
|
V(ProfileEntryHook) \
|
2013-07-05 10:34:02 +00:00
|
|
|
V(StoreGlobal) \
|
2013-03-04 14:03:27 +00:00
|
|
|
/* IC Handler stubs */ \
|
2013-05-02 16:32:47 +00:00
|
|
|
V(LoadField) \
|
2013-11-15 10:52:05 +00:00
|
|
|
V(KeyedLoadField) \
|
|
|
|
V(KeyedArrayCall)
|
2009-10-26 12:26:42 +00:00
|
|
|
|
|
|
|
// List of code stubs only used on ARM platforms.
|
2013-06-28 15:34:48 +00:00
|
|
|
#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
|
|
|
|
|
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
|
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) \
|
|
|
|
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.
|
2013-02-27 12:33:24 +00:00
|
|
|
Handle<Code> GetCode(Isolate* isolate);
|
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.
|
|
|
|
Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate);
|
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) {
|
|
|
|
return static_cast<Major>(code_stub->major_key());
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
virtual ~CodeStub() {}
|
|
|
|
|
2013-02-27 12:33:24 +00:00
|
|
|
static void GenerateStubsAheadOfTime(Isolate* isolate);
|
2013-11-15 10:52:05 +00:00
|
|
|
static void GenerateStubsRequiringBuiltinsAheadOfTime(Isolate* isolate);
|
2013-02-27 12:33:24 +00:00
|
|
|
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.
|
2012-11-22 07:58:59 +00:00
|
|
|
bool FindCodeInCache(Code** code_out, Isolate* isolate);
|
2011-11-09 15:44:13 +00:00
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
// Returns information for computing the number key.
|
|
|
|
virtual Major MajorKey() = 0;
|
|
|
|
virtual int MinorKey() = 0;
|
|
|
|
|
|
|
|
virtual InlineCacheState GetICState() {
|
|
|
|
return UNINITIALIZED;
|
|
|
|
}
|
2013-11-28 15:32:55 +00:00
|
|
|
virtual ExtraICState GetExtraICState() {
|
|
|
|
return kNoExtraICState;
|
2013-01-25 11:55:29 +00:00
|
|
|
}
|
2013-05-02 16:32:47 +00:00
|
|
|
virtual Code::StubType GetStubType() {
|
|
|
|
return Code::NORMAL;
|
|
|
|
}
|
|
|
|
virtual int GetStubFlags() {
|
|
|
|
return -1;
|
|
|
|
}
|
2013-04-18 09:50:46 +00:00
|
|
|
|
2013-07-05 09:26:22 +00:00
|
|
|
virtual void PrintName(StringStream* stream);
|
|
|
|
|
2013-10-02 11:27:37 +00:00
|
|
|
// Returns a name for logging/debugging purposes.
|
|
|
|
SmartArrayPointer<const char> GetName();
|
|
|
|
|
2013-04-18 09:50:46 +00:00
|
|
|
protected:
|
|
|
|
static bool CanUseFPRegisters();
|
|
|
|
|
|
|
|
// Generates the assembler code for the stub.
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
|
2013-04-18 09:50:46 +00:00
|
|
|
|
2013-10-10 08:45:40 +00:00
|
|
|
virtual void VerifyPlatformFeatures(Isolate* isolate);
|
2012-12-05 11:04:10 +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; }
|
|
|
|
|
2013-07-05 09:26:22 +00:00
|
|
|
virtual void PrintBaseName(StringStream* stream);
|
|
|
|
virtual void PrintState(StringStream* stream) { }
|
|
|
|
|
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.
|
2012-12-18 16:25:45 +00:00
|
|
|
void RecordCodeGeneration(Code* code, Isolate* isolate);
|
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.
|
2012-11-22 07:58:59 +00:00
|
|
|
virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-12-09 09:26:14 +00:00
|
|
|
|
|
|
|
// If a stub uses a special cache override this.
|
|
|
|
virtual bool UseSpecialCache() { return false; }
|
|
|
|
|
2008-07-03 15:10:15 +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());
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class PlatformCodeStub : public CodeStub {
|
|
|
|
public:
|
|
|
|
// Retrieve the code for the stub. Generate the code if needed.
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
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
|
|
|
|
2013-11-15 10:52:05 +00:00
|
|
|
enum ContinuationType { NORMAL_CONTINUATION, TAIL_CALL_CONTINUATION };
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
struct CodeStubInterfaceDescriptor {
|
2013-04-18 20:37:27 +00:00
|
|
|
CodeStubInterfaceDescriptor();
|
2012-12-18 16:25:45 +00:00
|
|
|
int register_param_count_;
|
2013-11-13 10:07:04 +00:00
|
|
|
|
2013-10-18 14:55:21 +00:00
|
|
|
Register stack_parameter_count_;
|
2013-04-25 16:00:32 +00:00
|
|
|
// 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_;
|
2013-11-15 10:52:05 +00:00
|
|
|
ContinuationType continuation_type_;
|
2013-04-02 11:28:01 +00:00
|
|
|
StubFunctionMode function_mode_;
|
2012-12-18 16:25:45 +00:00
|
|
|
Register* register_params_;
|
2013-11-13 10:07:04 +00:00
|
|
|
|
2013-01-07 10:06:11 +00:00
|
|
|
Address deoptimization_handler_;
|
2013-11-13 10:07:04 +00:00
|
|
|
HandlerArgumentsMode handler_arguments_mode_;
|
2013-03-08 21:07:55 +00:00
|
|
|
|
2013-11-15 10:52:05 +00:00
|
|
|
bool initialized() const { return register_param_count_ >= 0; }
|
|
|
|
|
|
|
|
bool HasTailCallContinuation() const {
|
|
|
|
return continuation_type_ == TAIL_CALL_CONTINUATION;
|
|
|
|
}
|
|
|
|
|
2013-03-08 21:07:55 +00:00
|
|
|
int environment_length() const {
|
|
|
|
return register_param_count_;
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
|
|
ExternalReference miss_handler() {
|
|
|
|
ASSERT(has_miss_handler_);
|
|
|
|
return miss_handler_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool has_miss_handler() {
|
|
|
|
return has_miss_handler_;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
Register GetParameterRegister(int index) const {
|
2013-11-13 10:07:04 +00:00
|
|
|
return register_params_[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsParameterCountRegister(int index) {
|
|
|
|
return GetParameterRegister(index).is(stack_parameter_count_);
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetHandlerParameterCount() {
|
|
|
|
int params = environment_length();
|
|
|
|
if (handler_arguments_mode_ == PASS_ARGUMENTS) {
|
|
|
|
params += 1;
|
|
|
|
}
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
2013-05-24 11:44:55 +00:00
|
|
|
private:
|
|
|
|
ExternalReference miss_handler_;
|
|
|
|
bool has_miss_handler_;
|
2012-12-18 16:25:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
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
|
|
|
struct PlatformCallInterfaceDescriptor;
|
|
|
|
|
|
|
|
|
|
|
|
struct CallInterfaceDescriptor {
|
|
|
|
CallInterfaceDescriptor()
|
|
|
|
: register_param_count_(-1),
|
|
|
|
register_params_(NULL),
|
|
|
|
param_representations_(NULL),
|
|
|
|
platform_specific_descriptor_(NULL) { }
|
|
|
|
|
|
|
|
bool initialized() const { return register_param_count_ >= 0; }
|
|
|
|
|
|
|
|
int environment_length() const {
|
|
|
|
return register_param_count_;
|
|
|
|
}
|
|
|
|
|
|
|
|
Representation GetParameterRepresentation(int index) const {
|
|
|
|
return param_representations_[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
Register GetParameterRegister(int index) const {
|
|
|
|
return register_params_[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
PlatformCallInterfaceDescriptor* platform_specific_descriptor() const {
|
|
|
|
return platform_specific_descriptor_;
|
|
|
|
}
|
|
|
|
|
|
|
|
int register_param_count_;
|
|
|
|
Register* register_params_;
|
|
|
|
Representation* param_representations_;
|
|
|
|
PlatformCallInterfaceDescriptor* platform_specific_descriptor_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
2013-05-24 11:44:55 +00:00
|
|
|
explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
|
|
|
|
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
|
|
|
|
|
|
|
CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
|
|
|
|
return isolate->code_stub_interface_descriptor(MajorKey());
|
|
|
|
}
|
|
|
|
|
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(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) = 0;
|
2013-04-18 20:37:27 +00:00
|
|
|
|
|
|
|
// Retrieve the code for the stub. Generate the code if needed.
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
|
2013-04-18 20:37:27 +00:00
|
|
|
|
|
|
|
virtual int NotMissMinorKey() = 0;
|
|
|
|
|
|
|
|
Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
|
|
|
|
|
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);
|
|
|
|
virtual int MinorKey() {
|
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
|
|
|
|
#include "ia32/code-stubs-ia32.h"
|
|
|
|
#elif V8_TARGET_ARCH_X64
|
|
|
|
#include "x64/code-stubs-x64.h"
|
|
|
|
#elif V8_TARGET_ARCH_ARM
|
|
|
|
#include "arm/code-stubs-arm.h"
|
|
|
|
#elif V8_TARGET_ARCH_MIPS
|
|
|
|
#include "mips/code-stubs-mips.h"
|
|
|
|
#else
|
|
|
|
#error Unsupported target architecture.
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
ToNumberStub() { }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-07-23 06:02:54 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
2011-01-28 14:18:26 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return ToNumber; }
|
2013-07-23 06:02:54 +00:00
|
|
|
int NotMissMinorKey() { 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:
|
|
|
|
NumberToStringStub() {}
|
|
|
|
|
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
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:
|
|
|
|
virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
|
|
|
|
virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-08-27 11:55:08 +00:00
|
|
|
class FastNewClosureStub : public HydrogenCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2013-04-11 16:28:19 +00:00
|
|
|
explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
|
|
|
|
: language_mode_(language_mode),
|
|
|
|
is_generator_(is_generator) { }
|
2011-03-17 20:28:30 +00:00
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-08-27 11:55:08 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
LanguageMode language_mode() const { return language_mode_; }
|
|
|
|
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> {};
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
Major MajorKey() { return FastNewClosure; }
|
2013-08-27 11:55:08 +00:00
|
|
|
int NotMissMinorKey() {
|
2013-04-11 16:28:19 +00:00
|
|
|
return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
|
|
|
|
IsGeneratorBits::encode(is_generator_);
|
|
|
|
}
|
2011-03-17 20:28:30 +00:00
|
|
|
|
2011-11-24 15:17:04 +00:00
|
|
|
LanguageMode language_mode_;
|
2013-04-11 16:28:19 +00:00
|
|
|
bool is_generator_;
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class FastNewContextStub : public PlatformCodeStub {
|
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
|
|
|
|
|
|
|
explicit FastNewContextStub(int slots) : slots_(slots) {
|
2011-10-06 15:59:02 +00:00
|
|
|
ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
|
2010-08-30 11:48:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
2011-01-21 11:28:35 +00:00
|
|
|
int slots_;
|
2011-01-25 13:01:45 +00:00
|
|
|
|
|
|
|
Major MajorKey() { return FastNewContext; }
|
|
|
|
int MinorKey() { return slots_; }
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class FastNewBlockContextStub : public PlatformCodeStub {
|
2011-10-06 15:59:02 +00:00
|
|
|
public:
|
|
|
|
static const int kMaximumSlots = 64;
|
|
|
|
|
|
|
|
explicit FastNewBlockContextStub(int slots) : slots_(slots) {
|
|
|
|
ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int slots_;
|
|
|
|
|
|
|
|
Major MajorKey() { return FastNewBlockContext; }
|
|
|
|
int MinorKey() { return slots_; }
|
|
|
|
};
|
|
|
|
|
2013-04-04 17:55:43 +00:00
|
|
|
class FastCloneShallowArrayStub : public HydrogenCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
|
|
|
// Maximum length of copied elements array.
|
|
|
|
static const int kMaximumClonedLength = 8;
|
|
|
|
enum Mode {
|
|
|
|
CLONE_ELEMENTS,
|
2011-10-19 11:36:55 +00:00
|
|
|
CLONE_DOUBLE_ELEMENTS,
|
2011-11-17 14:55:26 +00:00
|
|
|
COPY_ON_WRITE_ELEMENTS,
|
2013-01-08 09:03:16 +00:00
|
|
|
CLONE_ANY_ELEMENTS,
|
2013-01-17 08:41:27 +00:00
|
|
|
LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
2013-01-08 09:03:16 +00:00
|
|
|
static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
|
|
|
|
|
2013-01-17 08:41:27 +00:00
|
|
|
FastCloneShallowArrayStub(Mode mode,
|
|
|
|
AllocationSiteMode allocation_site_mode,
|
|
|
|
int length)
|
2013-05-24 11:44:55 +00:00
|
|
|
: mode_(mode),
|
2013-01-17 08:41:27 +00:00
|
|
|
allocation_site_mode_(allocation_site_mode),
|
2010-08-30 11:48:07 +00:00
|
|
|
length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
|
2011-11-21 13:27:44 +00:00
|
|
|
ASSERT_GE(length_, 0);
|
|
|
|
ASSERT_LE(length_, kMaximumClonedLength);
|
2010-08-30 11:48:07 +00:00
|
|
|
}
|
|
|
|
|
2013-04-04 17:55:43 +00:00
|
|
|
Mode mode() const { return mode_; }
|
|
|
|
int length() const { return length_; }
|
|
|
|
AllocationSiteMode allocation_site_mode() const {
|
|
|
|
return allocation_site_mode_;
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind ComputeElementsKind() const {
|
|
|
|
switch (mode()) {
|
|
|
|
case CLONE_ELEMENTS:
|
|
|
|
case COPY_ON_WRITE_ELEMENTS:
|
|
|
|
return FAST_ELEMENTS;
|
|
|
|
case CLONE_DOUBLE_ELEMENTS:
|
|
|
|
return FAST_DOUBLE_ELEMENTS;
|
|
|
|
case CLONE_ANY_ELEMENTS:
|
|
|
|
/*fall-through*/;
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
return LAST_ELEMENTS_KIND;
|
|
|
|
}
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-04-04 17:55:43 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Mode mode_;
|
2013-01-17 08:41:27 +00:00
|
|
|
AllocationSiteMode allocation_site_mode_;
|
2010-08-30 11:48:07 +00:00
|
|
|
int length_;
|
|
|
|
|
2013-01-17 08:41:27 +00:00
|
|
|
class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
|
|
|
|
class ModeBits: public BitField<Mode, 1, 4> {};
|
|
|
|
class LengthBits: public BitField<int, 5, 4> {};
|
|
|
|
// Ensure data fits within available bits.
|
|
|
|
STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
|
|
|
|
STATIC_ASSERT(kFastCloneModeCount < 16);
|
|
|
|
STATIC_ASSERT(kMaximumClonedLength < 16);
|
2010-08-30 11:48:07 +00:00
|
|
|
Major MajorKey() { return FastCloneShallowArray; }
|
2013-04-18 20:37:27 +00:00
|
|
|
int NotMissMinorKey() {
|
2013-01-17 08:41:27 +00:00
|
|
|
return AllocationSiteModeBits::encode(allocation_site_mode_)
|
|
|
|
| ModeBits::encode(mode_)
|
|
|
|
| LengthBits::encode(length_);
|
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;
|
|
|
|
|
2013-04-18 20:37:27 +00:00
|
|
|
explicit FastCloneShallowObjectStub(int length)
|
2013-05-24 11:44:55 +00:00
|
|
|
: 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_; }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-02-26 13:08:08 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
2011-11-21 13:27:44 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
int length_;
|
|
|
|
|
|
|
|
Major MajorKey() { return FastCloneShallowObject; }
|
2013-04-18 20:37:27 +00:00
|
|
|
int NotMissMinorKey() { 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:
|
|
|
|
explicit CreateAllocationSiteStub() { }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-07-08 10:02:16 +00:00
|
|
|
|
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return CreateAllocationSite; }
|
|
|
|
int NotMissMinorKey() { return 0; }
|
|
|
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
2011-07-13 11:08:25 +00:00
|
|
|
explicit InstanceofStub(Flags flags) : 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);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return Instanceof; }
|
2011-01-05 11:17:37 +00:00
|
|
|
int MinorKey() { 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;
|
|
|
|
}
|
|
|
|
|
2011-07-13 11:08:25 +00:00
|
|
|
virtual void PrintName(StringStream* stream);
|
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);
|
2013-12-18 22:51:23 +00:00
|
|
|
virtual void PrintName(StringStream* stream);
|
2013-09-12 17:59:41 +00:00
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
|
|
|
|
virtual int MinorKey() { return argument_count_; }
|
|
|
|
|
|
|
|
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:
|
|
|
|
virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
|
|
|
|
virtual int MinorKey() { return 0; }
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
explicit MathPowStub(ExponentType exponent_type)
|
|
|
|
: exponent_type_(exponent_type) { }
|
2010-12-07 11:31:57 +00:00
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual CodeStub::Major MajorKey() { return MathPow; }
|
2011-12-02 08:06:37 +00:00
|
|
|
virtual int MinorKey() { return exponent_type_; }
|
|
|
|
|
|
|
|
ExponentType exponent_type_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-01-21 14:53:29 +00:00
|
|
|
class ICStub: public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
explicit ICStub(Code::Kind kind) : 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
|
|
|
|
|
|
|
bool Describes(Code* code) {
|
|
|
|
return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
class KindBits: public BitField<Code::Kind, 0, 4> {};
|
|
|
|
virtual void FinishCode(Handle<Code> code) {
|
|
|
|
code->set_stub_info(MinorKey());
|
|
|
|
}
|
|
|
|
Code::Kind kind() { return kind_; }
|
|
|
|
|
2013-01-21 17:17:02 +00:00
|
|
|
virtual int MinorKey() {
|
|
|
|
return KindBits::encode(kind_);
|
|
|
|
}
|
|
|
|
|
2013-01-21 14:53:29 +00:00
|
|
|
private:
|
|
|
|
Code::Kind kind_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-01-21 17:54:36 +00:00
|
|
|
class FunctionPrototypeStub: public ICStub {
|
|
|
|
public:
|
|
|
|
explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
|
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-01-21 14:53:29 +00:00
|
|
|
class StringLengthStub: public ICStub {
|
|
|
|
public:
|
2013-09-13 09:57:48 +00:00
|
|
|
explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { }
|
2013-01-21 14:53:29 +00:00
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
2013-03-04 14:03:27 +00:00
|
|
|
STATIC_ASSERT(KindBits::kSize == 4);
|
2013-09-13 09:57:48 +00:00
|
|
|
virtual CodeStub::Major MajorKey() { return StringLength; }
|
2013-01-21 14:53:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-01-25 11:55:29 +00:00
|
|
|
class StoreICStub: public ICStub {
|
|
|
|
public:
|
|
|
|
StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
|
|
|
|
: ICStub(kind), strict_mode_(strict_mode) { }
|
|
|
|
|
|
|
|
protected:
|
2013-11-28 15:32:55 +00:00
|
|
|
virtual ExtraICState GetExtraICState() {
|
|
|
|
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> {};
|
|
|
|
virtual int MinorKey() {
|
|
|
|
return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
|
|
|
|
}
|
|
|
|
|
|
|
|
StrictModeFlag strict_mode_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class StoreArrayLengthStub: public StoreICStub {
|
|
|
|
public:
|
|
|
|
explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
|
|
|
|
: StoreICStub(kind, strict_mode) { }
|
|
|
|
virtual void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-02 16:32:47 +00:00
|
|
|
class HICStub: public HydrogenCodeStub {
|
|
|
|
public:
|
|
|
|
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; }
|
2013-03-05 17:38:35 +00:00
|
|
|
virtual int GetStubFlags() { return kind(); }
|
2013-11-15 10:52:05 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
HandlerStub() : HICStub() { }
|
|
|
|
virtual int NotMissMinorKey() { return bit_field_; }
|
|
|
|
int bit_field_;
|
2013-03-04 14:03:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LoadFieldStub: public HandlerStub {
|
|
|
|
public:
|
2013-11-07 10:17:13 +00:00
|
|
|
LoadFieldStub(bool inobject, int index, Representation representation) {
|
2013-05-08 15:02:08 +00:00
|
|
|
Initialize(Code::LOAD_IC, inobject, index, representation);
|
2013-05-02 16:32:47 +00:00
|
|
|
}
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-05-02 16:32:47 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_inobject() {
|
|
|
|
return InobjectBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
int offset() {
|
|
|
|
int index = IndexBits::decode(bit_field_);
|
|
|
|
int offset = index * kPointerSize;
|
|
|
|
if (is_inobject()) return offset;
|
|
|
|
return FixedArray::kHeaderSize + offset;
|
|
|
|
}
|
2013-03-04 14:03:27 +00:00
|
|
|
|
2013-05-08 15:02:08 +00:00
|
|
|
bool unboxed_double() {
|
|
|
|
return UnboxedDoubleBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
LoadFieldStub() : HandlerStub() { }
|
|
|
|
|
2013-05-08 15:02:08 +00:00
|
|
|
void Initialize(Code::Kind kind,
|
|
|
|
bool inobject,
|
|
|
|
int index,
|
|
|
|
Representation representation) {
|
|
|
|
bool unboxed_double = FLAG_track_double_fields && representation.IsDouble();
|
2013-05-02 16:32:47 +00:00
|
|
|
bit_field_ = KindBits::encode(kind)
|
|
|
|
| InobjectBits::encode(inobject)
|
2013-05-08 15:02:08 +00:00
|
|
|
| IndexBits::encode(index)
|
|
|
|
| UnboxedDoubleBits::encode(unboxed_double);
|
2013-05-02 16:32:47 +00:00
|
|
|
}
|
|
|
|
|
2013-03-04 14:03:27 +00:00
|
|
|
private:
|
|
|
|
STATIC_ASSERT(KindBits::kSize == 4);
|
2013-05-02 16:32:47 +00:00
|
|
|
class InobjectBits: public BitField<bool, 4, 1> {};
|
|
|
|
class IndexBits: public BitField<int, 5, 11> {};
|
2013-05-08 15:02:08 +00:00
|
|
|
class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
|
2013-03-04 14:03:27 +00:00
|
|
|
virtual CodeStub::Major MajorKey() { return LoadField; }
|
2013-05-02 16:32:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-11-07 10:17:13 +00:00
|
|
|
class StoreGlobalStub : public HandlerStub {
|
|
|
|
public:
|
2013-11-27 14:00:54 +00:00
|
|
|
explicit StoreGlobalStub(bool is_constant) {
|
|
|
|
bit_field_ = IsConstantBits::encode(is_constant);
|
2013-11-07 10:17:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
|
|
|
|
Map* receiver_map,
|
|
|
|
PropertyCell* cell) {
|
|
|
|
Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
|
|
|
|
// Replace the placeholder cell and global object map with the actual global
|
|
|
|
// cell and receiver map.
|
|
|
|
Map* cell_map = isolate->heap()->global_property_cell_map();
|
|
|
|
code->ReplaceNthObject(1, cell_map, cell);
|
|
|
|
code->ReplaceNthObject(1, isolate->heap()->meta_map(), receiver_map);
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Code::Kind kind() const { return Code::STORE_IC; }
|
|
|
|
|
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
2013-11-28 15:32:55 +00:00
|
|
|
virtual ExtraICState GetExtraICState() { return bit_field_; }
|
2013-11-07 10:17:13 +00:00
|
|
|
|
|
|
|
bool is_constant() {
|
|
|
|
return IsConstantBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
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:
|
|
|
|
virtual int NotMissMinorKey() { return GetExtraICState(); }
|
|
|
|
Major MajorKey() { return StoreGlobal; }
|
|
|
|
|
2013-11-27 14:00:54 +00:00
|
|
|
class IsConstantBits: public BitField<bool, 0, 1> {};
|
|
|
|
class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
|
2013-11-07 10:17:13 +00:00
|
|
|
|
|
|
|
int bit_field_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-02 16:32:47 +00:00
|
|
|
class KeyedLoadFieldStub: public LoadFieldStub {
|
|
|
|
public:
|
2013-05-08 15:02:08 +00:00
|
|
|
KeyedLoadFieldStub(bool inobject, int index, Representation representation)
|
|
|
|
: LoadFieldStub() {
|
|
|
|
Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
|
2013-03-04 14:03:27 +00:00
|
|
|
}
|
|
|
|
|
2013-05-02 16:32:47 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-05-02 16:32:47 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
|
2013-03-04 14:03:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-11-15 10:52:05 +00:00
|
|
|
class KeyedArrayCallStub: public HICStub {
|
|
|
|
public:
|
|
|
|
KeyedArrayCallStub(bool holey, int argc) : HICStub(), argc_(argc) {
|
2014-01-17 11:08:24 +00:00
|
|
|
bit_field_ = HoleyBits::encode(holey);
|
2013-11-15 10:52:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Code::Kind kind() const { return Code::KEYED_CALL_IC; }
|
2013-11-28 15:32:55 +00:00
|
|
|
virtual ExtraICState GetExtraICState() { return bit_field_; }
|
2013-11-15 10:52:05 +00:00
|
|
|
|
|
|
|
ElementsKind elements_kind() {
|
|
|
|
return HoleyBits::decode(bit_field_) ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int argc() { return argc_; }
|
|
|
|
virtual int GetStubFlags() { return argc(); }
|
|
|
|
|
|
|
|
static bool IsHoley(Handle<Code> code) {
|
2013-11-28 15:32:55 +00:00
|
|
|
ExtraICState state = code->extra_ic_state();
|
2013-11-15 10:52:05 +00:00
|
|
|
return HoleyBits::decode(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual int NotMissMinorKey() {
|
|
|
|
return GetExtraICState() | ArgcBits::encode(argc_);
|
|
|
|
}
|
|
|
|
|
2014-01-17 11:28:22 +00:00
|
|
|
class HoleyBits: public BitField<bool, 0, 1> {};
|
|
|
|
STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 1);
|
|
|
|
class ArgcBits: public BitField<int, 1, Code::kArgumentsBits> {};
|
2013-11-15 10:52:05 +00:00
|
|
|
virtual CodeStub::Major MajorKey() { return KeyedArrayCall; }
|
|
|
|
int bit_field_;
|
|
|
|
int argc_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-02 15:31:27 +00:00
|
|
|
class BinaryOpICStub : public HydrogenCodeStub {
|
2012-11-14 15:59:45 +00:00
|
|
|
public:
|
2013-12-02 13:14:07 +00:00
|
|
|
BinaryOpICStub(Token::Value op, OverwriteMode mode)
|
|
|
|
: HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {}
|
2013-10-04 08:17:11 +00:00
|
|
|
|
2013-12-02 13:14:07 +00:00
|
|
|
explicit BinaryOpICStub(const BinaryOpIC::State& state) : 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(
|
2013-12-02 13:14:07 +00:00
|
|
|
Isolate* isolate, 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-01-02 15:31:27 +00:00
|
|
|
virtual ExtraICState GetExtraICState() 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-01-02 15:31:27 +00:00
|
|
|
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_FINAL V8_OVERRIDE {
|
2013-12-02 13:14:07 +00:00
|
|
|
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
|
2013-10-01 18:00:02 +00:00
|
|
|
}
|
2013-06-04 07:49:45 +00:00
|
|
|
|
2013-12-02 13:14:07 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate) 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-01-02 15:31:27 +00:00
|
|
|
virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; }
|
|
|
|
virtual int NotMissMinorKey() V8_FINAL V8_OVERRIDE {
|
|
|
|
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-20 17:09:24 +00:00
|
|
|
class ArrayPushStub: public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
ArrayPushStub(ElementsKind kind, int argc) {
|
|
|
|
bit_field_ = ElementsKindBits::encode(kind) | ArgcBits::encode(argc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int arguments_count() { return ArgcBits::decode(bit_field_); }
|
|
|
|
ElementsKind elements_kind() {
|
|
|
|
return ElementsKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual CodeStub::Major MajorKey() { return ArrayPush; }
|
|
|
|
virtual int MinorKey() { return bit_field_; }
|
|
|
|
|
|
|
|
class ElementsKindBits: public BitField<ElementsKind, 0, 3> {};
|
|
|
|
class ArgcBits: public BitField<int, 3, Code::kArgumentsBits> {};
|
|
|
|
|
|
|
|
int bit_field_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
explicit BinaryOpICWithAllocationSiteStub(const BinaryOpIC::State& state)
|
|
|
|
: state_(state) {}
|
|
|
|
|
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
|
|
|
|
|
|
|
Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
|
|
|
|
Handle<AllocationSite> allocation_site) {
|
|
|
|
Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
|
|
|
|
// Replace the placeholder oddball with the actual allocation site.
|
|
|
|
code->ReplaceNthObject(1, isolate->heap()->oddball_map(), *allocation_site);
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
|
|
|
|
return Code::BINARY_OP_IC;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual InlineCacheState GetICState() V8_OVERRIDE {
|
|
|
|
return state_.GetICState();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ExtraICState GetExtraICState() V8_OVERRIDE {
|
|
|
|
return state_.GetExtraICState();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
|
|
|
|
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual void PrintState(StringStream* stream) V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual Major MajorKey() V8_OVERRIDE { return BinaryOpICWithAllocationSite; }
|
|
|
|
virtual int MinorKey() V8_OVERRIDE { return GetExtraICState(); }
|
|
|
|
|
|
|
|
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-01-09 13:22:18 +00:00
|
|
|
BinaryOpWithAllocationSiteStub(Token::Value op, OverwriteMode mode)
|
|
|
|
: BinaryOpICStub(op, mode) {}
|
|
|
|
|
2014-01-02 15:31:27 +00:00
|
|
|
explicit BinaryOpWithAllocationSiteStub(const BinaryOpIC::State& state)
|
|
|
|
: BinaryOpICStub(state) {}
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
virtual Code::Kind GetCodeKind() const V8_FINAL V8_OVERRIDE {
|
|
|
|
return Code::STUB;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual Major MajorKey() V8_OVERRIDE {
|
|
|
|
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-01-22 13:48:05 +00:00
|
|
|
StringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag)
|
2013-11-12 10:21:08 +00:00
|
|
|
: bit_field_(StringAddFlagsBits::encode(flags) |
|
|
|
|
PretenureFlagBits::encode(pretenure_flag)) {}
|
|
|
|
|
|
|
|
StringAddFlags flags() const {
|
|
|
|
return StringAddFlagsBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
PretenureFlag pretenure_flag() const {
|
|
|
|
return PretenureFlagBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2014-01-02 15:31:27 +00:00
|
|
|
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
|
|
|
|
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
|
|
|
|
}
|
|
|
|
|
2013-11-12 10:21:08 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
|
|
|
static void InstallDescriptors(Isolate* isolate);
|
|
|
|
|
|
|
|
// Parameters accessed via CodeStubGraphBuilder::GetParameter()
|
|
|
|
static const int 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-01-22 13:48:05 +00:00
|
|
|
virtual Major MajorKey() V8_OVERRIDE { return StringAdd; }
|
2013-11-12 10:21:08 +00:00
|
|
|
virtual int NotMissMinorKey() V8_OVERRIDE { return bit_field_; }
|
|
|
|
|
|
|
|
virtual void PrintBaseName(StringStream* stream) V8_OVERRIDE;
|
|
|
|
|
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:
|
2012-11-14 15:59:45 +00:00
|
|
|
ICCompareStub(Token::Value op,
|
|
|
|
CompareIC::State left,
|
|
|
|
CompareIC::State right,
|
|
|
|
CompareIC::State handler)
|
|
|
|
: op_(op),
|
|
|
|
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; }
|
|
|
|
|
2012-11-14 15:59:45 +00:00
|
|
|
static void DecodeMinorKey(int minor_key,
|
|
|
|
CompareIC::State* left_state,
|
|
|
|
CompareIC::State* right_state,
|
|
|
|
CompareIC::State* handler_state,
|
|
|
|
Token::Value* op);
|
|
|
|
|
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
|
|
|
|
2011-11-11 13:48:14 +00:00
|
|
|
virtual void FinishCode(Handle<Code> code) {
|
2012-11-14 15:59:45 +00:00
|
|
|
code->set_stub_info(MinorKey());
|
2011-11-11 13:48:14 +00:00
|
|
|
}
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
virtual CodeStub::Major MajorKey() { return CompareIC; }
|
|
|
|
virtual int MinorKey();
|
|
|
|
|
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);
|
2012-11-22 07:58:59 +00:00
|
|
|
virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
|
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
|
|
|
|
2013-07-11 17:20:57 +00:00
|
|
|
explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { }
|
2013-04-24 11:32:17 +00:00
|
|
|
|
2013-11-28 15:32:55 +00:00
|
|
|
CompareNilICStub(ExtraICState ic_state,
|
2013-05-24 11:44:55 +00:00
|
|
|
InitializationState init_state = INITIALIZED)
|
2013-07-11 17:20:57 +00:00
|
|
|
: HydrogenCodeStub(init_state),
|
|
|
|
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) {
|
2013-06-10 15:47:23 +00:00
|
|
|
return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
|
2013-04-24 11:32:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
static void InitializeForIsolate(Isolate* isolate) {
|
2013-06-10 15:47:23 +00:00
|
|
|
CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
|
2013-04-24 11:32:17 +00:00
|
|
|
compare_stub.InitializeInterfaceDescriptor(
|
|
|
|
isolate,
|
|
|
|
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
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-05-16 10:59:17 +00:00
|
|
|
|
2013-11-28 15:32:55 +00:00
|
|
|
virtual ExtraICState GetExtraICState() {
|
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
|
|
|
|
2013-07-05 09:26:22 +00:00
|
|
|
virtual void PrintState(StringStream* stream);
|
|
|
|
virtual void PrintBaseName(StringStream* stream);
|
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) { }
|
|
|
|
|
|
|
|
void Print(StringStream* stream) const;
|
|
|
|
};
|
|
|
|
|
2013-06-10 15:47:23 +00:00
|
|
|
CompareNilICStub(NilValue nil, InitializationState init_state)
|
2013-07-11 17:20:57 +00:00
|
|
|
: HydrogenCodeStub(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
|
|
|
|
2013-04-24 11:32:17 +00:00
|
|
|
virtual CodeStub::Major MajorKey() { return CompareNilIC; }
|
2013-05-16 10:59:17 +00:00
|
|
|
virtual int NotMissMinorKey() { 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);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class CEntryStub : public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2011-09-19 18:36:47 +00:00
|
|
|
explicit CEntryStub(int result_size,
|
|
|
|
SaveFPRegsMode save_doubles = kDontSaveFPRegs)
|
|
|
|
: 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
|
|
|
|
2013-10-10 08:45:40 +00:00
|
|
|
protected:
|
|
|
|
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
|
|
|
|
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
|
|
|
|
};
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
private:
|
|
|
|
void GenerateCore(MacroAssembler* masm,
|
|
|
|
Label* throw_normal_exception,
|
|
|
|
Label* throw_termination_exception,
|
|
|
|
Label* throw_out_of_memory_exception,
|
|
|
|
bool do_gc,
|
2011-01-25 07:49:39 +00:00
|
|
|
bool always_allocate_scope);
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
// Number of pointers/values returned.
|
2013-09-11 10:51:06 +00:00
|
|
|
Isolate* isolate_;
|
2010-08-30 11:48:07 +00:00
|
|
|
const int result_size_;
|
2011-09-19 18:36:47 +00:00
|
|
|
SaveFPRegsMode save_doubles_;
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
Major MajorKey() { return CEntry; }
|
|
|
|
int MinorKey();
|
|
|
|
|
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:
|
|
|
|
JSEntryStub() { }
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void GenerateBody(MacroAssembler* masm, bool is_construct);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return JSEntry; }
|
|
|
|
int MinorKey() { return 0; }
|
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:
|
|
|
|
JSConstructEntryStub() { }
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
int MinorKey() { return 1; }
|
|
|
|
|
2011-07-13 11:08:25 +00:00
|
|
|
virtual void PrintName(StringStream* stream) {
|
|
|
|
stream->Add("JSConstructEntryStub");
|
|
|
|
}
|
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,
|
2011-06-16 14:12:58 +00:00
|
|
|
NEW_NON_STRICT_FAST,
|
|
|
|
NEW_NON_STRICT_SLOW,
|
2011-03-17 20:28:41 +00:00
|
|
|
NEW_STRICT
|
2010-08-30 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
explicit ArgumentsAccessStub(Type type) : type_(type) { }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Type type_;
|
|
|
|
|
|
|
|
Major MajorKey() { return ArgumentsAccess; }
|
|
|
|
int MinorKey() { return type_; }
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
void GenerateReadElement(MacroAssembler* masm);
|
2011-06-16 14:12:58 +00:00
|
|
|
void GenerateNewStrict(MacroAssembler* masm);
|
|
|
|
void GenerateNewNonStrictFast(MacroAssembler* masm);
|
|
|
|
void GenerateNewNonStrictSlow(MacroAssembler* masm);
|
2011-03-17 20:28:41 +00:00
|
|
|
|
2011-07-13 11:08:25 +00:00
|
|
|
virtual void PrintName(StringStream* stream);
|
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:
|
|
|
|
RegExpExecStub() { }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return RegExpExec; }
|
|
|
|
int MinorKey() { return 0; }
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class RegExpConstructResultStub: public PlatformCodeStub {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
|
|
|
RegExpConstructResultStub() { }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return RegExpConstructResult; }
|
|
|
|
int MinorKey() { return 0; }
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class CallFunctionStub: public PlatformCodeStub {
|
2010-08-30 11:48:07 +00:00
|
|
|
public:
|
2011-09-13 12:53:28 +00:00
|
|
|
CallFunctionStub(int argc, CallFunctionFlags flags)
|
|
|
|
: argc_(argc), flags_(flags) { }
|
2010-08-30 11:48:07 +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());
|
|
|
|
}
|
|
|
|
|
2011-01-06 14:13:40 +00:00
|
|
|
static int ExtractArgcFromMinorKey(int minor_key) {
|
|
|
|
return ArgcBits::decode(minor_key);
|
|
|
|
}
|
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
private:
|
|
|
|
int argc_;
|
|
|
|
CallFunctionFlags flags_;
|
|
|
|
|
2011-07-13 11:08:25 +00:00
|
|
|
virtual void PrintName(StringStream* stream);
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
// Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
|
2014-01-14 12:04:10 +00:00
|
|
|
class FlagBits: public BitField<CallFunctionFlags, 0, 1> {};
|
|
|
|
class ArgcBits: public BitField<unsigned, 1, 32 - 1> {};
|
2010-08-30 11:48:07 +00:00
|
|
|
|
|
|
|
Major MajorKey() { return CallFunction; }
|
|
|
|
int MinorKey() {
|
|
|
|
// 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
|
|
|
}
|
|
|
|
|
2011-09-27 11:42:02 +00:00
|
|
|
bool RecordCallTarget() {
|
|
|
|
return (flags_ & RECORD_CALL_TARGET) != 0;
|
|
|
|
}
|
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:
|
|
|
|
explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2012-01-27 16:09:20 +00:00
|
|
|
virtual void FinishCode(Handle<Code> code) {
|
|
|
|
code->set_has_function_cache(RecordCallTarget());
|
|
|
|
}
|
|
|
|
|
2012-01-27 13:03:19 +00:00
|
|
|
private:
|
|
|
|
CallFunctionFlags flags_;
|
|
|
|
|
|
|
|
virtual void PrintName(StringStream* stream);
|
|
|
|
|
|
|
|
Major MajorKey() { return CallConstruct; }
|
|
|
|
int MinorKey() { return flags_; }
|
|
|
|
|
|
|
|
bool RecordCallTarget() {
|
|
|
|
return (flags_ & RECORD_CALL_TARGET) != 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
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
|
|
|
|
2013-11-15 17:53:35 +00:00
|
|
|
class KeyedLoadDictionaryElementStub : public HydrogenCodeStub {
|
2011-05-18 13:17:29 +00:00
|
|
|
public:
|
2012-12-18 16:25:45 +00:00
|
|
|
KeyedLoadDictionaryElementStub() {}
|
2011-05-18 13:17:29 +00:00
|
|
|
|
2013-11-15 17:53:35 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
|
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return KeyedLoadElement; }
|
|
|
|
int NotMissMinorKey() { return DICTIONARY_ELEMENTS; }
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class KeyedLoadDictionaryElementPlatformStub : public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
KeyedLoadDictionaryElementPlatformStub() {}
|
|
|
|
|
2011-05-18 13:17:29 +00:00
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2011-07-08 10:46:10 +00:00
|
|
|
private:
|
2013-04-18 20:37:27 +00:00
|
|
|
Major MajorKey() { return KeyedLoadElement; }
|
|
|
|
int MinorKey() { return DICTIONARY_ELEMENTS; }
|
|
|
|
|
2013-11-15 17:53:35 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementPlatformStub);
|
2012-12-18 16:25:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-07-12 12:28:32 +00:00
|
|
|
class DoubleToIStub : public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
DoubleToIStub(Register source,
|
|
|
|
Register destination,
|
|
|
|
int offset,
|
2013-08-26 12:24:03 +00:00
|
|
|
bool is_truncating,
|
|
|
|
bool skip_fastpath = false) : bit_field_(0) {
|
2013-07-12 12:28:32 +00:00
|
|
|
bit_field_ = SourceRegisterBits::encode(source.code_) |
|
|
|
|
DestinationRegisterBits::encode(destination.code_) |
|
|
|
|
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) |
|
|
|
|
SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
|
|
|
|
CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
|
2013-07-12 12:28:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Register source() {
|
|
|
|
Register result = { SourceRegisterBits::decode(bit_field_) };
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
Register destination() {
|
|
|
|
Register result = { DestinationRegisterBits::decode(bit_field_) };
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
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-10-10 08:45:40 +00:00
|
|
|
protected:
|
|
|
|
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
|
|
|
|
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
|
|
|
|
}
|
|
|
|
|
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
|
2013-10-04 08:17:11 +00:00
|
|
|
class SSEBits:
|
|
|
|
public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT
|
2013-07-12 12:28:32 +00:00
|
|
|
|
|
|
|
Major MajorKey() { return DoubleToI; }
|
|
|
|
int MinorKey() { return bit_field_; }
|
|
|
|
|
|
|
|
int bit_field_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class KeyedLoadFastElementStub : public HydrogenCodeStub {
|
|
|
|
public:
|
2013-05-24 11:44:55 +00:00
|
|
|
KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
|
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_);
|
|
|
|
}
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2012-12-18 16:25:45 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
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
|
|
|
|
2013-02-26 13:08:08 +00:00
|
|
|
Major MajorKey() { return KeyedLoadElement; }
|
2013-04-18 20:37:27 +00:00
|
|
|
int NotMissMinorKey() { return bit_field_; }
|
2013-02-26 13:08:08 +00:00
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
|
2011-05-18 13:17:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-03-20 10:37:13 +00:00
|
|
|
class KeyedStoreFastElementStub : public HydrogenCodeStub {
|
|
|
|
public:
|
|
|
|
KeyedStoreFastElementStub(bool is_js_array,
|
|
|
|
ElementsKind elements_kind,
|
2013-05-24 11:44:55 +00:00
|
|
|
KeyedAccessStoreMode mode) {
|
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_);
|
|
|
|
}
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-03-20 10:37:13 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
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_;
|
|
|
|
|
2013-04-18 20:37:27 +00:00
|
|
|
Major MajorKey() { return KeyedStoreElement; }
|
|
|
|
int NotMissMinorKey() { return bit_field_; }
|
|
|
|
|
2013-03-20 10:37:13 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-02-04 12:01:59 +00:00
|
|
|
class TransitionElementsKindStub : public HydrogenCodeStub {
|
|
|
|
public:
|
|
|
|
TransitionElementsKindStub(ElementsKind from_kind,
|
2013-05-24 11:44:55 +00:00
|
|
|
ElementsKind to_kind) {
|
2013-02-04 12:01:59 +00:00
|
|
|
bit_field_ = FromKindBits::encode(from_kind) |
|
|
|
|
ToKindBits::encode(to_kind);
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind from_kind() const {
|
|
|
|
return FromKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementsKind to_kind() const {
|
|
|
|
return ToKindBits::decode(bit_field_);
|
|
|
|
}
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-02-04 12:01:59 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
|
|
|
class FromKindBits: public BitField<ElementsKind, 8, 8> {};
|
|
|
|
class ToKindBits: public BitField<ElementsKind, 0, 8> {};
|
|
|
|
uint32_t bit_field_;
|
|
|
|
|
2013-02-26 13:08:08 +00:00
|
|
|
Major MajorKey() { return TransitionElementsKind; }
|
2013-04-18 20:37:27 +00:00
|
|
|
int NotMissMinorKey() { 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-01-09 15:07:23 +00:00
|
|
|
ArrayConstructorStubBase(ElementsKind kind,
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode) {
|
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:
|
|
|
|
void BasePrintName(const char* name, StringStream* stream);
|
|
|
|
|
2013-04-25 16:00:32 +00:00
|
|
|
private:
|
|
|
|
int NotMissMinorKey() { return bit_field_; }
|
|
|
|
|
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(
|
|
|
|
ElementsKind kind,
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
|
2014-01-09 15:07:23 +00:00
|
|
|
: ArrayConstructorStubBase(kind, override_mode) {
|
2013-03-01 16:06:34 +00:00
|
|
|
}
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
2013-04-18 20:37:27 +00:00
|
|
|
Major MajorKey() { return ArrayNoArgumentConstructor; }
|
|
|
|
|
2013-12-18 22:51:23 +00:00
|
|
|
virtual void PrintName(StringStream* stream) {
|
|
|
|
BasePrintName("ArrayNoArgumentConstructorStub", stream);
|
|
|
|
}
|
|
|
|
|
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(
|
|
|
|
ElementsKind kind,
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
|
2014-01-09 15:07:23 +00:00
|
|
|
: ArrayConstructorStubBase(kind, override_mode) {
|
2013-04-25 16:00:32 +00:00
|
|
|
}
|
2013-03-01 16:06:34 +00:00
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
2013-04-18 20:37:27 +00:00
|
|
|
Major MajorKey() { return ArraySingleArgumentConstructor; }
|
|
|
|
|
2013-12-18 22:51:23 +00:00
|
|
|
virtual void PrintName(StringStream* stream) {
|
|
|
|
BasePrintName("ArraySingleArgumentConstructorStub", stream);
|
|
|
|
}
|
|
|
|
|
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(
|
|
|
|
ElementsKind kind,
|
2013-06-28 13:16:14 +00:00
|
|
|
AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
|
2014-01-09 15:07:23 +00:00
|
|
|
: ArrayConstructorStubBase(kind, override_mode) {
|
2013-04-25 16:00:32 +00:00
|
|
|
}
|
2013-03-01 16:06:34 +00:00
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-03-01 16:06:34 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
2013-04-18 20:37:27 +00:00
|
|
|
Major MajorKey() { return ArrayNArgumentsConstructor; }
|
|
|
|
|
2013-12-18 22:51:23 +00:00
|
|
|
virtual void PrintName(StringStream* stream) {
|
|
|
|
BasePrintName("ArrayNArgumentsConstructorStub", stream);
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
explicit InternalArrayConstructorStubBase(ElementsKind kind) {
|
|
|
|
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:
|
|
|
|
int NotMissMinorKey() { return kind_; }
|
|
|
|
|
|
|
|
ElementsKind kind_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class InternalArrayNoArgumentConstructorStub : public
|
|
|
|
InternalArrayConstructorStubBase {
|
|
|
|
public:
|
|
|
|
explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
|
|
|
|
: InternalArrayConstructorStubBase(kind) { }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return InternalArrayNoArgumentConstructor; }
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class InternalArraySingleArgumentConstructorStub : public
|
|
|
|
InternalArrayConstructorStubBase {
|
|
|
|
public:
|
|
|
|
explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
|
|
|
|
: InternalArrayConstructorStubBase(kind) { }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return InternalArraySingleArgumentConstructor; }
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class InternalArrayNArgumentsConstructorStub : public
|
|
|
|
InternalArrayConstructorStubBase {
|
|
|
|
public:
|
|
|
|
explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
|
|
|
|
: InternalArrayConstructorStubBase(kind) { }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-06-05 10:43:18 +00:00
|
|
|
|
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Major MajorKey() { return InternalArrayNArgumentsConstructor; }
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class KeyedStoreElementStub : public PlatformCodeStub {
|
2011-05-18 13:17:29 +00:00
|
|
|
public:
|
2011-07-08 10:46:10 +00:00
|
|
|
KeyedStoreElementStub(bool is_js_array,
|
2012-02-10 12:36:05 +00:00
|
|
|
ElementsKind elements_kind,
|
2013-03-06 21:51:07 +00:00
|
|
|
KeyedAccessStoreMode store_mode)
|
2012-02-10 12:36:05 +00:00
|
|
|
: is_js_array_(is_js_array),
|
|
|
|
elements_kind_(elements_kind),
|
2013-03-06 21:51:07 +00:00
|
|
|
store_mode_(store_mode),
|
2012-09-27 11:31:26 +00:00
|
|
|
fp_registers_(CanUseFPRegisters()) { }
|
2011-05-18 13:17:29 +00:00
|
|
|
|
2011-07-08 10:46:10 +00:00
|
|
|
Major MajorKey() { return KeyedStoreElement; }
|
|
|
|
int MinorKey() {
|
2012-02-10 12:36:05 +00:00
|
|
|
return ElementsKindBits::encode(elements_kind_) |
|
|
|
|
IsJSArrayBits::encode(is_js_array_) |
|
2013-03-06 21:51:07 +00:00
|
|
|
StoreModeBits::encode(store_mode_) |
|
2012-09-27 11:31:26 +00:00
|
|
|
FPRegisters::encode(fp_registers_);
|
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> {};
|
|
|
|
class FPRegisters: public BitField<bool, 13, 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_;
|
2012-09-27 11:31:26 +00:00
|
|
|
bool fp_registers_;
|
2011-07-08 10:46:10 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
|
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(); }
|
2011-07-28 13:33:51 +00:00
|
|
|
void Print(StringStream* stream) const;
|
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
|
|
|
|
2013-05-29 14:49:28 +00:00
|
|
|
explicit ToBooleanStub(Types types = Types())
|
|
|
|
: types_(types) { }
|
2013-11-28 15:32:55 +00:00
|
|
|
explicit ToBooleanStub(ExtraICState state)
|
2013-05-29 14:49:28 +00:00
|
|
|
: types_(static_cast<byte>(state)) { }
|
|
|
|
|
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_; }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-05-29 14:49:28 +00:00
|
|
|
virtual void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
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; }
|
2013-07-05 09:26:22 +00:00
|
|
|
virtual void PrintState(StringStream* stream);
|
2011-06-22 08:28:35 +00:00
|
|
|
|
2011-09-15 11:30:45 +00:00
|
|
|
virtual bool SometimesSetsUpAFrame() { return false; }
|
|
|
|
|
2013-05-29 14:49:28 +00:00
|
|
|
static void InitializeForIsolate(Isolate* isolate) {
|
|
|
|
ToBooleanStub stub;
|
|
|
|
stub.InitializeInterfaceDescriptor(
|
|
|
|
isolate,
|
|
|
|
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) {
|
|
|
|
return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
|
2011-07-22 12:42:40 +00:00
|
|
|
}
|
2011-07-21 13:51:04 +00:00
|
|
|
|
2013-11-28 15:32:55 +00:00
|
|
|
virtual ExtraICState GetExtraICState() {
|
2013-05-29 14:49:28 +00:00
|
|
|
return types_.ToIntegral();
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
Major MajorKey() { return ToBoolean; }
|
|
|
|
int NotMissMinorKey() { return GetExtraICState(); }
|
|
|
|
|
|
|
|
explicit ToBooleanStub(InitializationState init_state) :
|
|
|
|
HydrogenCodeStub(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
|
|
|
|
2013-07-17 11:37:20 +00:00
|
|
|
class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
|
2011-10-13 10:53:31 +00:00
|
|
|
public:
|
2013-07-17 11:37:20 +00:00
|
|
|
ElementsTransitionAndStoreStub(ElementsKind from_kind,
|
|
|
|
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)
|
2013-07-17 11:37:20 +00:00
|
|
|
: from_kind_(from_kind),
|
|
|
|
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_; }
|
|
|
|
|
2013-09-03 06:57:16 +00:00
|
|
|
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
2013-07-17 11:37:20 +00:00
|
|
|
|
|
|
|
void InitializeInterfaceDescriptor(
|
|
|
|
Isolate* isolate,
|
|
|
|
CodeStubInterfaceDescriptor* descriptor);
|
|
|
|
|
|
|
|
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> {};
|
|
|
|
|
|
|
|
Major MajorKey() { return ElementsTransitionAndStore; }
|
|
|
|
int NotMissMinorKey() {
|
|
|
|
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:
|
2012-09-27 11:31:26 +00:00
|
|
|
StoreArrayLiteralElementStub()
|
|
|
|
: fp_registers_(CanUseFPRegisters()) { }
|
2011-10-31 14:42:06 +00:00
|
|
|
|
|
|
|
private:
|
2012-09-27 11:31:26 +00:00
|
|
|
class FPRegisters: public BitField<bool, 0, 1> {};
|
|
|
|
|
2011-10-31 14:42:06 +00:00
|
|
|
Major MajorKey() { return StoreArrayLiteralElement; }
|
2012-09-27 11:31:26 +00:00
|
|
|
int MinorKey() { return FPRegisters::encode(fp_registers_); }
|
2011-10-31 14:42:06 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2012-09-27 11:31:26 +00:00
|
|
|
bool fp_registers_;
|
|
|
|
|
2011-10-31 14:42:06 +00:00
|
|
|
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:
|
2013-04-02 11:28:01 +00:00
|
|
|
explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
|
2013-04-04 17:55:43 +00:00
|
|
|
: fp_registers_(CanUseFPRegisters()), 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:
|
2013-04-04 17:55:43 +00:00
|
|
|
class FPRegisters: public BitField<bool, 0, 1> {};
|
|
|
|
class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {};
|
|
|
|
|
2013-01-29 09:12:20 +00:00
|
|
|
Major MajorKey() { return StubFailureTrampoline; }
|
2013-04-04 17:55:43 +00:00
|
|
|
int MinorKey() {
|
|
|
|
return FPRegisters::encode(fp_registers_) |
|
|
|
|
FunctionModeField::encode(function_mode_);
|
|
|
|
}
|
2013-01-29 09:12:20 +00:00
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
2013-04-04 17:55:43 +00:00
|
|
|
bool fp_registers_;
|
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);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-11-15 10:52:05 +00:00
|
|
|
class StubFailureTailCallTrampolineStub : public PlatformCodeStub {
|
|
|
|
public:
|
|
|
|
StubFailureTailCallTrampolineStub() : fp_registers_(CanUseFPRegisters()) {}
|
|
|
|
|
|
|
|
static void GenerateAheadOfTime(Isolate* isolate);
|
|
|
|
|
|
|
|
private:
|
|
|
|
class FPRegisters: public BitField<bool, 0, 1> {};
|
|
|
|
Major MajorKey() { return StubFailureTailCallTrampoline; }
|
|
|
|
int MinorKey() { return FPRegisters::encode(fp_registers_); }
|
|
|
|
|
|
|
|
void Generate(MacroAssembler* masm);
|
|
|
|
|
|
|
|
bool fp_registers_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(StubFailureTailCallTrampolineStub);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-12-18 16:25:45 +00:00
|
|
|
class ProfileEntryHookStub : public PlatformCodeStub {
|
2012-07-17 15:18:15 +00:00
|
|
|
public:
|
|
|
|
explicit ProfileEntryHookStub() {}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
|
|
Major MajorKey() { return ProfileEntryHook; }
|
|
|
|
int MinorKey() { return 0; }
|
|
|
|
|
|
|
|
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_
|