// Copyright 2012 the V8 project authors. All rights reserved.
-// 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.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#ifndef V8_IA32_MACRO_ASSEMBLER_IA32_H_
#define V8_IA32_MACRO_ASSEMBLER_IA32_H_
-#include "assembler.h"
-#include "frames.h"
-#include "v8globals.h"
+#include "src/assembler.h"
+#include "src/bailout-reason.h"
+#include "src/frames.h"
+#include "src/globals.h"
namespace v8 {
namespace internal {
enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
+enum PointersToHereCheck {
+ kPointersToHereMaybeInteresting,
+ kPointersToHereAreAlwaysInteresting
+};
enum RegisterValueType {
};
-bool AreAliased(Register r1, Register r2, Register r3, Register r4);
+#ifdef DEBUG
+bool AreAliased(Register reg1,
+ Register reg2,
+ Register reg3 = no_reg,
+ Register reg4 = no_reg,
+ Register reg5 = no_reg,
+ Register reg6 = no_reg,
+ Register reg7 = no_reg,
+ Register reg8 = no_reg);
+#endif
// MacroAssembler implements a collection of frequently used macros.
// macro assembler.
MacroAssembler(Isolate* isolate, void* buffer, int size);
+ void Load(Register dst, const Operand& src, Representation r);
+ void Store(Register src, const Operand& dst, Representation r);
+
+ // Operations on roots in the root-array.
+ void LoadRoot(Register destination, Heap::RootListIndex index);
+ void StoreRoot(Register source, Register scratch, Heap::RootListIndex index);
+ void CompareRoot(Register with, Register scratch, Heap::RootListIndex index);
+ // These methods can only be used with constant roots (i.e. non-writable
+ // and not in new space).
+ void CompareRoot(Register with, Heap::RootListIndex index);
+ void CompareRoot(const Operand& with, Heap::RootListIndex index);
+
// ---------------------------------------------------------------------------
// GC Support
enum RememberedSetFinalAction {
Label* condition_met,
Label::Distance condition_met_distance = Label::kFar);
- void CheckMapDeprecated(Handle<Map> map,
- Register scratch,
- Label* if_deprecated);
-
// Check if object is in new space. Jumps if the object is not in new space.
// The register scratch can be object itself, but scratch will be clobbered.
void JumpIfNotInNewSpace(Register object,
Register scratch,
SaveFPRegsMode save_fp,
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
- SmiCheck smi_check = INLINE_SMI_CHECK);
+ SmiCheck smi_check = INLINE_SMI_CHECK,
+ PointersToHereCheck pointers_to_here_check_for_value =
+ kPointersToHereMaybeInteresting);
// As above, but the offset has the tag presubtracted. For use with
// Operand(reg, off).
Register scratch,
SaveFPRegsMode save_fp,
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
- SmiCheck smi_check = INLINE_SMI_CHECK) {
+ SmiCheck smi_check = INLINE_SMI_CHECK,
+ PointersToHereCheck pointers_to_here_check_for_value =
+ kPointersToHereMaybeInteresting) {
RecordWriteField(context,
offset + kHeapObjectTag,
value,
scratch,
save_fp,
remembered_set_action,
- smi_check);
+ smi_check,
+ pointers_to_here_check_for_value);
}
// Notify the garbage collector that we wrote a pointer into a fixed array.
Register index,
SaveFPRegsMode save_fp,
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
- SmiCheck smi_check = INLINE_SMI_CHECK);
+ SmiCheck smi_check = INLINE_SMI_CHECK,
+ PointersToHereCheck pointers_to_here_check_for_value =
+ kPointersToHereMaybeInteresting);
// For page containing |object| mark region covering |address|
// dirty. |object| is the object being stored into, |value| is the
Register value,
SaveFPRegsMode save_fp,
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
- SmiCheck smi_check = INLINE_SMI_CHECK);
+ SmiCheck smi_check = INLINE_SMI_CHECK,
+ PointersToHereCheck pointers_to_here_check_for_value =
+ kPointersToHereMaybeInteresting);
// For page containing |object| mark the region covering the object's map
// dirty. |object| is the object being stored into, |map| is the Map object
Register scratch2,
SaveFPRegsMode save_fp);
-#ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
// Debugger Support
void DebugBreak();
-#endif
+
+ // Generates function and stub prologue code.
+ void StubPrologue();
+ void Prologue(bool code_pre_aging);
// Enter specific kind of exit frame. Expects the number of
// arguments in register eax and sets up the number of arguments in
// Leave the current exit frame. Expects the return value in
// register eax (untouched).
- void LeaveApiExitFrame();
+ void LeaveApiExitFrame(bool restore_context);
// Find the function context up the context chain.
void LoadContext(Register dst, int context_chain_length);
Register scratch,
Label* no_map_match);
- // Load the initial map for new Arrays from a JSFunction.
- void LoadInitialArrayMap(Register function_in,
- Register scratch,
- Register map_out,
- bool can_have_holes);
-
- void LoadGlobalContext(Register global_context);
-
// Load the global function with the given index.
void LoadGlobalFunction(int index, Register function);
void LoadFromSafepointRegisterSlot(Register dst, Register src);
void LoadHeapObject(Register result, Handle<HeapObject> object);
+ void CmpHeapObject(Register reg, Handle<HeapObject> object);
void PushHeapObject(Handle<HeapObject> object);
void LoadObject(Register result, Handle<Object> object) {
- ALLOW_HANDLE_DEREF(isolate(), "heap object check");
+ AllowDeferredHandleDereference heap_object_check;
if (object->IsHeapObject()) {
LoadHeapObject(result, Handle<HeapObject>::cast(object));
} else {
- Set(result, Immediate(object));
+ Move(result, Immediate(object));
+ }
+ }
+
+ void CmpObject(Register reg, Handle<Object> object) {
+ AllowDeferredHandleDereference heap_object_check;
+ if (object->IsHeapObject()) {
+ CmpHeapObject(reg, Handle<HeapObject>::cast(object));
+ } else {
+ cmp(reg, Immediate(object));
}
}
+ // Compare the given value and the value of weak cell.
+ void CmpWeakValue(Register value, Handle<WeakCell> cell, Register scratch);
+
+ void GetWeakValue(Register value, Handle<WeakCell> cell);
+
+ // Load the value of the weak cell in the value register. Branch to the given
+ // miss label if the weak cell was cleared.
+ void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss);
+
// ---------------------------------------------------------------------------
// JavaScript invokes
- // Set up call kind marking in ecx. The method takes ecx as an
- // explicit first parameter to make the code more readable at the
- // call sites.
- void SetCallKind(Register dst, CallKind kind);
-
// Invoke the JavaScript function code by either calling or jumping.
void InvokeCode(Register code,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind) {
- InvokeCode(Operand(code), expected, actual, flag, call_wrapper, call_kind);
+ const CallWrapper& call_wrapper) {
+ InvokeCode(Operand(code), expected, actual, flag, call_wrapper);
}
void InvokeCode(const Operand& code,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind);
-
- void InvokeCode(Handle<Code> code,
- const ParameterCount& expected,
- const ParameterCount& actual,
- RelocInfo::Mode rmode,
- InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind);
+ const CallWrapper& call_wrapper);
// Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking.
void InvokeFunction(Register function,
const ParameterCount& actual,
InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind);
+ const CallWrapper& call_wrapper);
+
+ void InvokeFunction(Register function,
+ const ParameterCount& expected,
+ const ParameterCount& actual,
+ InvokeFlag flag,
+ const CallWrapper& call_wrapper);
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind);
+ const CallWrapper& call_wrapper);
// Invoke specified builtin JavaScript function. Adds an entry to
// the unresolved list if the name does not resolve.
void GetBuiltinEntry(Register target, Builtins::JavaScript id);
// Expression support
- void Set(Register dst, const Immediate& x);
- void Set(const Operand& dst, const Immediate& x);
+ // cvtsi2sd instruction only writes to the low 64-bit of dst register, which
+ // hinders register renaming and makes dependence chains longer. So we use
+ // xorps to clear the dst register before cvtsi2sd to solve this issue.
+ void Cvtsi2sd(XMMRegister dst, Register src) { Cvtsi2sd(dst, Operand(src)); }
+ void Cvtsi2sd(XMMRegister dst, const Operand& src);
// Support for constant splitting.
bool IsUnsafeImmediate(const Immediate& x);
- void SafeSet(Register dst, const Immediate& x);
+ void SafeMove(Register dst, const Immediate& x);
void SafePush(const Immediate& x);
- // Compare against a known root, e.g. undefined, null, true, ...
- void CompareRoot(Register with, Heap::RootListIndex index);
- void CompareRoot(const Operand& with, Heap::RootListIndex index);
-
// Compare object type for heap object.
// Incoming register is heap_object and outgoing register is map.
void CmpObjectType(Register heap_object, InstanceType type, Register map);
Register scratch1,
XMMRegister scratch2,
Label* fail,
- bool specialize_for_processor,
int offset = 0);
- // Compare an object's map with the specified map and its transitioned
- // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. FLAGS are set with
- // result of map compare. If multiple map compares are required, the compare
- // sequences branches to early_success.
- void CompareMap(Register obj,
- Handle<Map> map,
- Label* early_success,
- CompareMapMode mode = REQUIRE_EXACT_MAP);
+ // Compare an object's map with the specified map.
+ void CompareMap(Register obj, Handle<Map> map);
// Check if the map of an object is equal to a specified map and branch to
// label if not. Skip the smi check if not required (object is known to be a
void CheckMap(Register obj,
Handle<Map> map,
Label* fail,
- SmiCheckType smi_check_type,
- CompareMapMode mode = REQUIRE_EXACT_MAP);
-
- // Check if the map of an object is equal to a specified map and branch to a
- // specified target if equal. Skip the smi check if not required (object is
- // known to be a heap object)
- void DispatchMap(Register obj,
- Register unused,
- Handle<Map> map,
- Handle<Code> success,
- SmiCheckType smi_check_type);
+ SmiCheckType smi_check_type);
+
+ // Check if the map of an object is equal to a specified weak map and branch
+ // to a specified target if equal. Skip the smi check if not required
+ // (object is known to be a heap object)
+ void DispatchWeakMap(Register obj, Register scratch1, Register scratch2,
+ Handle<WeakCell> cell, Handle<Code> success,
+ SmiCheckType smi_check_type);
// Check if the object in register heap_object is a string. Afterwards the
// register map contains the object map and the register instance_type
XMMRegister scratch_reg,
Register result_reg);
+ void SlowTruncateToI(Register result_reg, Register input_reg,
+ int offset = HeapNumber::kValueOffset - kHeapObjectTag);
+
+ void TruncateHeapNumberToI(Register result_reg, Register input_reg);
+ void TruncateDoubleToI(Register result_reg, XMMRegister input_reg);
+
+ void DoubleToI(Register result_reg, XMMRegister input_reg,
+ XMMRegister scratch, MinusZeroMode minus_zero_mode,
+ Label* lost_precision, Label* is_nan, Label* minus_zero,
+ Label::Distance dst = Label::kFar);
// Smi tagging support.
void SmiTag(Register reg) {
j(not_carry, is_smi);
}
- void LoadUint32(XMMRegister dst, Register src, XMMRegister scratch);
+ void LoadUint32(XMMRegister dst, Register src) {
+ LoadUint32(dst, Operand(src));
+ }
+ void LoadUint32(XMMRegister dst, const Operand& src);
// Jump the register contains a smi.
inline void JumpIfSmi(Register value,
void LoadInstanceDescriptors(Register map, Register descriptors);
void EnumLength(Register dst, Register map);
void NumberOfOwnDescriptors(Register dst, Register map);
+ void LoadAccessor(Register dst, Register holder, int accessor_index,
+ AccessorComponent accessor);
template<typename Field>
void DecodeField(Register reg) {
static const int shift = Field::kShift;
+ static const int mask = Field::kMask >> Field::kShift;
+ if (shift != 0) {
+ sar(reg, shift);
+ }
+ and_(reg, Immediate(mask));
+ }
+
+ template<typename Field>
+ void DecodeFieldToSmi(Register reg) {
+ static const int shift = Field::kShift;
static const int mask = (Field::kMask >> Field::kShift) << kSmiTagSize;
- sar(reg, shift);
+ STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0);
+ STATIC_ASSERT(kSmiTag == 0);
+ if (shift < kSmiTagSize) {
+ shl(reg, kSmiTagSize - shift);
+ } else if (shift > kSmiTagSize) {
+ sar(reg, shift - kSmiTagSize);
+ }
and_(reg, Immediate(mask));
}
+
void LoadPowerOf2(XMMRegister dst, Register scratch, int power);
// Abort execution if argument is not a number, enabled via --debug-code.
// Abort execution if argument is not a name, enabled via --debug-code.
void AssertName(Register object);
+ // Abort execution if argument is not undefined or an AllocationSite, enabled
+ // via --debug-code.
+ void AssertUndefinedOrAllocationSite(Register object);
+
// ---------------------------------------------------------------------------
// Exception handling
- // Push a new try handler and link it into try handler chain.
- void PushTryHandler(StackHandler::Kind kind, int handler_index);
-
- // Unlink the stack handler on top of the stack from the try handler chain.
- void PopTryHandler();
-
- // Throw to the top handler in the try hander chain.
- void Throw(Register value);
+ // Push a new stack handler and link it into stack handler chain.
+ void PushStackHandler();
- // Throw past all JS frames to the top JS entry frame.
- void ThrowUncatchable(Register value);
+ // Unlink the stack handler on top of the stack from the stack handler chain.
+ void PopStackHandler();
// ---------------------------------------------------------------------------
// Inline caching support
void AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
- Label* gc_required);
+ Label* gc_required,
+ MutableMode mode = IMMUTABLE);
// Allocate a sequential string. All the header fields of the string object
// are initialized.
Register scratch2,
Register scratch3,
Label* gc_required);
- void AllocateAsciiString(Register result,
- Register length,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Label* gc_required);
- void AllocateAsciiString(Register result,
- int length,
- Register scratch1,
- Register scratch2,
- Label* gc_required);
+ void AllocateOneByteString(Register result, Register length,
+ Register scratch1, Register scratch2,
+ Register scratch3, Label* gc_required);
+ void AllocateOneByteString(Register result, int length, Register scratch1,
+ Register scratch2, Label* gc_required);
// Allocate a raw cons string object. Only the map field of the result is
// initialized.
Register scratch1,
Register scratch2,
Label* gc_required);
- void AllocateAsciiConsString(Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required);
+ void AllocateOneByteConsString(Register result, Register scratch1,
+ Register scratch2, Label* gc_required);
// Allocate a raw sliced string object. Only the map field of the result is
// initialized.
Register scratch1,
Register scratch2,
Label* gc_required);
- void AllocateAsciiSlicedString(Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required);
+ void AllocateOneByteSlicedString(Register result, Register scratch1,
+ Register scratch2, Label* gc_required);
// Copy memory, byte-by-byte, from source to destination. Not optimized for
// long or aligned copies.
void NegativeZeroTest(Register result, Register op1, Register op2,
Register scratch, Label* then_label);
+ // Machine code version of Map::GetConstructor().
+ // |temp| holds |result|'s map when done.
+ void GetMapConstructor(Register result, Register map, Register temp);
+
// Try to get function prototype of a function and puts the value in
// the result register. Checks that the function really is a
// function and jumps to the miss label if the fast checks fail. The
Label* miss,
bool miss_on_bound_function = false);
- // Generates code for reporting that an illegal operation has
- // occurred.
- void IllegalOperation(int num_arguments);
-
// Picks out an array index from the hash field.
// Register use:
// hash - holds the index's hash. Clobbered.
void StubReturn(int argc);
// Call a runtime routine.
- void CallRuntime(const Runtime::Function* f, int num_arguments);
- void CallRuntimeSaveDoubles(Runtime::FunctionId id);
+ void CallRuntime(const Runtime::Function* f,
+ int num_arguments,
+ SaveFPRegsMode save_doubles = kDontSaveFPRegs);
+ void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
+ const Runtime::Function* function = Runtime::FunctionForId(id);
+ CallRuntime(function, function->nargs, kSaveFPRegs);
+ }
// Convenience function: Same as above, but takes the fid instead.
- void CallRuntime(Runtime::FunctionId id, int num_arguments);
+ void CallRuntime(Runtime::FunctionId id,
+ int num_arguments,
+ SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
+ CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
+ }
// Convenience function: call an external reference.
void CallExternalReference(ExternalReference ref, int num_arguments);
void CallCFunction(ExternalReference function, int num_arguments);
void CallCFunction(Register function, int num_arguments);
- // Prepares stack to put arguments (aligns and so on). Reserves
- // space for return value if needed (assumes the return value is a handle).
- // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
- // etc. Saves context (esi). If space was reserved for return value then
- // stores the pointer to the reserved slot into esi.
- void PrepareCallApiFunction(int argc, bool returns_handle);
-
- // Calls an API function. Allocates HandleScope, extracts returned value
- // from handle and propagates exceptions. Clobbers ebx, edi and
- // caller-save registers. Restores context. On return removes
- // stack_space * kPointerSize (GCed).
- void CallApiFunctionAndReturn(Address function_address,
- int stack_space,
- bool returns_handle,
- int return_value_offset_from_ebp);
-
// Jump to a runtime routine.
void JumpToExternalReference(const ExternalReference& ext);
void Drop(int element_count);
void Call(Label* target) { call(target); }
+ void Push(Register src) { push(src); }
+ void Pop(Register dst) { pop(dst); }
+
+ // Non-SSE2 instructions.
+ void Pextrd(Register dst, XMMRegister src, int8_t imm8);
+ void Pinsrd(XMMRegister dst, Register src, int8_t imm8) {
+ Pinsrd(dst, Operand(src), imm8);
+ }
+ void Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8);
+
+ void Lzcnt(Register dst, Register src) { Lzcnt(dst, Operand(src)); }
+ void Lzcnt(Register dst, const Operand& src);
// Emit call to the code we are currently generating.
void CallSelf() {
// Move if the registers are not identical.
void Move(Register target, Register source);
+ // Move a constant into a destination using the most efficient encoding.
+ void Move(Register dst, const Immediate& x);
+ void Move(const Operand& dst, const Immediate& x);
+
+ // Move an immediate into an XMM register.
+ void Move(XMMRegister dst, uint32_t src);
+ void Move(XMMRegister dst, uint64_t src);
+ void Move(XMMRegister dst, double src) { Move(dst, bit_cast<uint64_t>(src)); }
+
// Push a handle value.
void Push(Handle<Object> handle) { push(Immediate(handle)); }
void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
Handle<Object> CodeObject() {
- ASSERT(!code_object_.is_null());
+ DCHECK(!code_object_.is_null());
return code_object_;
}
- // Insert code to verify that the x87 stack has the specified depth (0-7)
- void VerifyX87StackDepth(uint32_t depth);
+ // Emit code for a truncating division by a constant. The dividend register is
+ // unchanged, the result is in edx, and eax gets clobbered.
+ void TruncatingDiv(Register dividend, int32_t divisor);
// ---------------------------------------------------------------------------
// StatsCounter support
// Calls Abort(msg) if the condition cc is not satisfied.
// Use --debug_code to enable.
- void Assert(Condition cc, const char* msg);
+ void Assert(Condition cc, BailoutReason reason);
void AssertFastElements(Register elements);
// Like Assert(), but always enabled.
- void Check(Condition cc, const char* msg);
+ void Check(Condition cc, BailoutReason reason);
// Print a message to stdout and abort execution.
- void Abort(const char* msg);
+ void Abort(BailoutReason reason);
// Check that the stack is aligned.
void CheckStackAlignment();
// Verify restrictions about code generated in stubs.
void set_generating_stub(bool value) { generating_stub_ = value; }
bool generating_stub() { return generating_stub_; }
- void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
- bool allow_stub_calls() { return allow_stub_calls_; }
void set_has_frame(bool value) { has_frame_ = value; }
bool has_frame() { return has_frame_; }
inline bool AllowThisStubCall(CodeStub* stub);
// ---------------------------------------------------------------------------
// String utilities.
- // Check whether the instance type represents a flat ASCII string. Jump to the
- // label if not. If the instance type can be scratched specify same register
- // for both instance type and scratch.
- void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
- Register scratch,
- Label* on_not_flat_ascii_string);
+ // Generate code to do a lookup in the number string cache. If the number in
+ // the register object is found in the cache the generated code falls through
+ // with the result in the result register. The object and the result register
+ // can be the same. If the number is not found in the cache the code jumps to
+ // the label not_found with only the content of register object unchanged.
+ void LookupNumberStringCache(Register object,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* not_found);
+
+ // Check whether the instance type represents a flat one-byte string. Jump to
+ // the label if not. If the instance type can be scratched specify same
+ // register for both instance type and scratch.
+ void JumpIfInstanceTypeIsNotSequentialOneByte(
+ Register instance_type, Register scratch,
+ Label* on_not_flat_one_byte_string);
- // Checks if both objects are sequential ASCII strings, and jumps to label
+ // Checks if both objects are sequential one-byte strings, and jumps to label
// if either is not.
- void JumpIfNotBothSequentialAsciiStrings(Register object1,
- Register object2,
- Register scratch1,
- Register scratch2,
- Label* on_not_flat_ascii_strings);
+ void JumpIfNotBothSequentialOneByteStrings(
+ Register object1, Register object2, Register scratch1, Register scratch2,
+ Label* on_not_flat_one_byte_strings);
+
+ // Checks if the given register or operand is a unique name
+ void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name,
+ Label::Distance distance = Label::kFar) {
+ JumpIfNotUniqueNameInstanceType(Operand(reg), not_unique_name, distance);
+ }
+
+ void JumpIfNotUniqueNameInstanceType(Operand operand, Label* not_unique_name,
+ Label::Distance distance = Label::kFar);
+
+ void EmitSeqStringSetCharCheck(Register string,
+ Register index,
+ Register value,
+ uint32_t encoding_mask);
static int SafepointRegisterStackIndex(Register reg) {
return SafepointRegisterStackIndex(reg.code());
// Activation support.
void EnterFrame(StackFrame::Type type);
+ void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type);
// Expects object in eax and returns map with validated enum cache
// in eax. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime);
- // AllocationSiteInfo support. Arrays may have an associated
- // AllocationSiteInfo object that can be checked for in order to pretransition
+ // AllocationMemento support. Arrays may have an associated
+ // AllocationMemento object that can be checked for in order to pretransition
// to another type.
// On entry, receiver_reg should point to the array object.
// scratch_reg gets clobbered.
- // If allocation info is present, conditional code is set to equal
- void TestJSArrayForAllocationSiteInfo(Register receiver_reg,
- Register scratch_reg);
+ // If allocation info is present, conditional code is set to equal.
+ void TestJSArrayForAllocationMemento(Register receiver_reg,
+ Register scratch_reg,
+ Label* no_memento_found);
+
+ void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
+ Register scratch_reg,
+ Label* memento_found) {
+ Label no_memento_found;
+ TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
+ &no_memento_found);
+ j(equal, memento_found);
+ bind(&no_memento_found);
+ }
+
+ // Jumps to found label if a prototype map has dictionary elements.
+ void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
+ Register scratch1, Label* found);
private:
bool generating_stub_;
- bool allow_stub_calls_;
bool has_frame_;
// This handle will be patched with the code object on installation.
Handle<Object> code_object_;
bool* definitely_mismatches,
InvokeFlag flag,
Label::Distance done_distance,
- const CallWrapper& call_wrapper = NullCallWrapper(),
- CallKind call_kind = CALL_AS_METHOD);
+ const CallWrapper& call_wrapper = NullCallWrapper());
void EnterExitFramePrologue();
void EnterExitFrameEpilogue(int argc, bool save_doubles);
- void LeaveExitFrameEpilogue();
+ void LeaveExitFrameEpilogue(bool restore_context);
// Allocation support helpers.
void LoadAllocationTopHelper(Register result,
Register scratch,
AllocationFlags flags);
- // Helper for PopHandleScope. Allowed to perform a GC and returns
- // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
- // possibly returns a failure object indicating an allocation failure.
- MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
- Register scratch,
- bool gc_allowed);
-
// Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
void InNewSpace(Register object,
Register scratch,
Register bitmap_reg,
Register mask_reg);
- // Helper for throwing exceptions. Compute a handler address and jump to
- // it. See the implementation for register usage.
- void JumpToHandlerEntry();
-
// Compute memory operands for safepoint stack slots.
Operand SafepointRegisterSlot(Register reg);
static int SafepointRegisterStackIndex(int reg_code);
}
+inline Operand FixedArrayElementOperand(Register array,
+ Register index_as_smi,
+ int additional_offset = 0) {
+ int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize;
+ return FieldOperand(array, index_as_smi, times_half_pointer_size, offset);
+}
+
+
inline Operand ContextOperand(Register context, int index) {
return Operand(context, Context::SlotOffset(index));
}
}
-// Generates an Operand for saving parameters after PrepareCallApiFunction.
-Operand ApiParameterOperand(int index, bool returns_handle);
-
-
#ifdef GENERATED_CODE_COVERAGE
extern void LogGeneratedCodeCoverage(const char* file_line);
#define CODE_COVERAGE_STRINGIFY(x) #x