Commit 51a76d8c authored by jgruber's avatar jgruber Committed by Commit Bot

[masm,ia32] Add initial indirect load implementations

A first baby-step towards embedded builtins on ia32. This adds the
initial implementation for indirect load functionality (they still
depend on embedded external references to get the roots pointer).

External reference operands still directly embed external references.
We can change these sites to be root-relative once the root register
exists.

Drive-by: replace raw jmp(HeapObject), call(HeapObject),
mov(HeapObject) uses by their macro-assembler counterparts and add
sanity-checks to ensure we're not calling them by accident when
generating isolate-independent code.

Bug: v8:6666
Change-Id: Ide11273721bcdaaee06934eedeca9f39346d1d50
Reviewed-on: https://chromium-review.googlesource.com/1170687
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55332}
parent ec0a495c
......@@ -329,7 +329,7 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
// limit" is checked.
ExternalReference real_stack_limit =
ExternalReference::address_of_real_stack_limit(masm->isolate());
__ mov(scratch1, Operand::StaticVariable(real_stack_limit));
__ mov(scratch1, __ StaticVariable(real_stack_limit));
// Make scratch2 the space we have left. The stack might already be overflowed
// here which will cause scratch2 to become negative.
__ mov(scratch2, esp);
......@@ -356,7 +356,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Setup the context (we need to use the caller context from the isolate).
ExternalReference context_address = ExternalReference::Create(
IsolateAddressId::kContextAddress, masm->isolate());
__ mov(esi, Operand::StaticVariable(context_address));
__ mov(esi, __ StaticVariable(context_address));
// Load the previous frame pointer (ebx) to access C arguments
__ mov(ebx, Operand(ebp, 0));
......@@ -458,13 +458,13 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
Label stepping_prepared;
ExternalReference debug_hook =
ExternalReference::debug_hook_on_function_call_address(masm->isolate());
__ cmpb(Operand::StaticVariable(debug_hook), Immediate(0));
__ cmpb(__ StaticVariable(debug_hook), Immediate(0));
__ j(not_equal, &prepare_step_in_if_stepping);
// Flood function if we need to continue stepping in the suspended generator.
ExternalReference debug_suspended_generator =
ExternalReference::debug_suspended_generator_address(masm->isolate());
__ cmp(edx, Operand::StaticVariable(debug_suspended_generator));
__ cmp(edx, __ StaticVariable(debug_suspended_generator));
__ j(equal, &prepare_step_in_suspended_generator);
__ bind(&stepping_prepared);
......@@ -757,7 +757,7 @@ static void AdvanceBytecodeOffsetOrReturn(MacroAssembler* masm,
#define JUMP_IF_EQUAL(NAME) \
__ cmpb(bytecode, \
Immediate(static_cast<int>(interpreter::Bytecode::k##NAME))); \
__ j(equal, if_return, Label::kNear);
__ j(equal, if_return);
RETURN_BYTECODE_LIST(JUMP_IF_EQUAL)
#undef JUMP_IF_EQUAL
......@@ -845,7 +845,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ sub(ecx, ebx);
ExternalReference stack_limit =
ExternalReference::address_of_real_stack_limit(masm->isolate());
__ cmp(ecx, Operand::StaticVariable(stack_limit));
__ cmp(ecx, __ StaticVariable(stack_limit));
__ j(above_equal, &ok);
__ CallRuntime(Runtime::kThrowStackOverflow);
__ bind(&ok);
......@@ -1690,7 +1690,7 @@ void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
Label done;
ExternalReference real_stack_limit =
ExternalReference::address_of_real_stack_limit(masm->isolate());
__ mov(edx, Operand::StaticVariable(real_stack_limit));
__ mov(edx, __ StaticVariable(real_stack_limit));
// Make edx the space we have left. The stack might already be overflowed
// here which will cause edx to become negative.
__ neg(edx);
......@@ -2516,7 +2516,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
Label okay;
ExternalReference pending_exception_address = ExternalReference::Create(
IsolateAddressId::kPendingExceptionAddress, masm->isolate());
__ cmp(edx, Operand::StaticVariable(pending_exception_address));
__ cmp(edx, __ StaticVariable(pending_exception_address));
// Cannot use check here as it attempts to generate call into runtime.
__ j(equal, &okay, Label::kNear);
__ int3();
......@@ -2556,9 +2556,9 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
}
// Retrieve the handler context, SP and FP.
__ mov(esi, Operand::StaticVariable(pending_handler_context_address));
__ mov(esp, Operand::StaticVariable(pending_handler_sp_address));
__ mov(ebp, Operand::StaticVariable(pending_handler_fp_address));
__ mov(esi, __ StaticVariable(pending_handler_context_address));
__ mov(esp, __ StaticVariable(pending_handler_sp_address));
__ mov(ebp, __ StaticVariable(pending_handler_fp_address));
// If the handler is a JS frame, restore the context to the frame. Note that
// the context will be set to (esi == 0) for non-JS frames.
......@@ -2575,7 +2575,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
__ ResetSpeculationPoisonRegister();
// Compute the handler entry address and jump to it.
__ mov(edi, Operand::StaticVariable(pending_handler_entrypoint_address));
__ mov(edi, __ StaticVariable(pending_handler_entrypoint_address));
__ jmp(edi);
}
......
......@@ -3632,7 +3632,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIA32StackCheck: {
ExternalReference const stack_limit =
ExternalReference::address_of_stack_limit(__ isolate());
__ cmp(esp, Operand::StaticVariable(stack_limit));
__ cmp(esp, tasm()->StaticVariable(stack_limit));
break;
}
case kIA32Word32AtomicPairLoad: {
......
......@@ -3278,6 +3278,15 @@ void Assembler::emit_operand(XMMRegister reg, Operand adr) {
}
void Assembler::emit_operand(int code, Operand adr) {
// Isolate-independent code may not embed relocatable addresses.
DCHECK(!options().isolate_independent_code ||
adr.rmode_ != RelocInfo::CODE_TARGET);
DCHECK(!options().isolate_independent_code ||
adr.rmode_ != RelocInfo::EMBEDDED_OBJECT);
// TODO(jgruber,v8:6666): Enable once kRootRegister exists.
// DCHECK(!options().isolate_independent_code ||
// adr.rmode_ != RelocInfo::EXTERNAL_REFERENCE);
const unsigned length = adr.len_;
DCHECK_GT(length, 0);
......
......@@ -271,6 +271,15 @@ class Immediate BASE_EMBEDDED {
return value_.immediate;
}
bool is_external_reference() const {
return rmode() == RelocInfo::EXTERNAL_REFERENCE;
}
ExternalReference external_reference() const {
DCHECK(is_external_reference());
return bit_cast<ExternalReference>(immediate());
}
bool is_zero() const { return RelocInfo::IsNone(rmode_) && immediate() == 0; }
bool is_int8() const {
return RelocInfo::IsNone(rmode_) && i::is_int8(immediate());
......@@ -362,16 +371,6 @@ class V8_EXPORT_PRIVATE Operand {
RelocInfo::INTERNAL_REFERENCE);
}
static Operand StaticVariable(const ExternalReference& ext) {
return Operand(ext.address(), RelocInfo::EXTERNAL_REFERENCE);
}
static Operand StaticArray(Register index,
ScaleFactor scale,
const ExternalReference& arr) {
return Operand(index, scale, arr.address(), RelocInfo::EXTERNAL_REFERENCE);
}
static Operand ForRegisterPlusImmediate(Register base, Immediate imm) {
return Operand(base, imm.value_.immediate, imm.rmode_);
}
......@@ -413,9 +412,9 @@ class V8_EXPORT_PRIVATE Operand {
byte buf_[6];
// The number of bytes in buf_.
uint8_t len_;
uint8_t len_ = 0;
// Only valid if len_ > 4.
RelocInfo::Mode rmode_;
RelocInfo::Mode rmode_ = RelocInfo::NONE;
// TODO(clemensh): Get rid of this friendship, or make Operand immutable.
friend class Assembler;
......
......@@ -40,7 +40,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ push(Immediate(StackFrame::TypeToMarker(marker))); // marker
ExternalReference context_address =
ExternalReference::Create(IsolateAddressId::kContextAddress, isolate());
__ push(Operand::StaticVariable(context_address)); // context
__ push(__ StaticVariable(context_address)); // context
// Save callee-saved registers (C calling conventions).
__ push(edi);
__ push(esi);
......@@ -49,14 +49,14 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Save copies of the top frame descriptor on the stack.
ExternalReference c_entry_fp =
ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate());
__ push(Operand::StaticVariable(c_entry_fp));
__ push(__ StaticVariable(c_entry_fp));
// If this is the outermost JS call, set js_entry_sp value.
ExternalReference js_entry_sp =
ExternalReference::Create(IsolateAddressId::kJSEntrySPAddress, isolate());
__ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
__ cmp(__ StaticVariable(js_entry_sp), Immediate(0));
__ j(not_equal, &not_outermost_js, Label::kNear);
__ mov(Operand::StaticVariable(js_entry_sp), ebp);
__ mov(__ StaticVariable(js_entry_sp), ebp);
__ push(Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ jmp(&invoke, Label::kNear);
__ bind(&not_outermost_js);
......@@ -71,7 +71,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// field in the JSEnv and return a failure sentinel.
ExternalReference pending_exception = ExternalReference::Create(
IsolateAddressId::kPendingExceptionAddress, isolate());
__ mov(Operand::StaticVariable(pending_exception), eax);
__ mov(__ StaticVariable(pending_exception), eax);
__ mov(eax, Immediate(isolate()->factory()->exception()));
__ jmp(&exit);
......@@ -93,11 +93,11 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ pop(ebx);
__ cmp(ebx, Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ j(not_equal, &not_outermost_js_2);
__ mov(Operand::StaticVariable(js_entry_sp), Immediate(0));
__ mov(__ StaticVariable(js_entry_sp), Immediate(0));
__ bind(&not_outermost_js_2);
// Restore the top frame descriptor from the stack.
__ pop(Operand::StaticVariable(ExternalReference::Create(
__ pop(__ StaticVariable(ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, isolate())));
// Restore callee-saved registers (C calling conventions).
......@@ -197,9 +197,9 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
DCHECK(edx == function_address);
// Allocate HandleScope in callee-save registers.
__ mov(ebx, Operand::StaticVariable(next_address));
__ mov(edi, Operand::StaticVariable(limit_address));
__ add(Operand::StaticVariable(level_address), Immediate(1));
__ mov(ebx, __ StaticVariable(next_address));
__ mov(edi, __ StaticVariable(limit_address));
__ add(__ StaticVariable(level_address), Immediate(1));
if (FLAG_log_timer_events) {
FrameScope frame(masm, StackFrame::MANUAL);
......@@ -251,10 +251,10 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
__ bind(&prologue);
// No more valid handles (the result handle was the last one). Restore
// previous handle scope.
__ mov(Operand::StaticVariable(next_address), ebx);
__ sub(Operand::StaticVariable(level_address), Immediate(1));
__ mov(__ StaticVariable(next_address), ebx);
__ sub(__ StaticVariable(level_address), Immediate(1));
__ Assert(above_equal, AbortReason::kInvalidHandleScopeLevel);
__ cmp(edi, Operand::StaticVariable(limit_address));
__ cmp(edi, __ StaticVariable(limit_address));
__ j(not_equal, &delete_allocated_handles);
// Leave the API exit frame.
......@@ -267,7 +267,7 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
// Check if the function scheduled an exception.
ExternalReference scheduled_exception_address =
ExternalReference::scheduled_exception_address(isolate);
__ cmp(Operand::StaticVariable(scheduled_exception_address),
__ cmp(__ StaticVariable(scheduled_exception_address),
Immediate(isolate->factory()->the_hole_value()));
__ j(not_equal, &promote_scheduled_exception);
......@@ -323,7 +323,7 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
ExternalReference delete_extensions =
ExternalReference::delete_handle_scope_extensions();
__ bind(&delete_allocated_handles);
__ mov(Operand::StaticVariable(limit_address), edi);
__ mov(__ StaticVariable(limit_address), edi);
__ mov(edi, eax);
__ mov(Operand(esp, 0),
Immediate(ExternalReference::isolate_address(isolate)));
......
......@@ -47,7 +47,7 @@ void Deoptimizer::TableEntryGenerator::Generate() {
ExternalReference c_entry_fp_address =
ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate());
__ mov(Operand::StaticVariable(c_entry_fp_address), ebp);
__ mov(masm()->StaticVariable(c_entry_fp_address), ebp);
const int kSavedRegistersAreaSize =
kNumberOfRegisters * kPointerSize + kDoubleRegsSize + kFloatRegsSize;
......
This diff is collapsed.
......@@ -103,17 +103,15 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void CheckStackAlignment();
// Nop, because ia32 does not have a root register.
// TODO(jgruber,v8:6666): Implement one.
void InitializeRootRegister() {}
// Move a constant into a destination using the most efficient encoding.
void Move(Register dst, const Immediate& x);
void Move(Register dst, Smi* source) { Move(dst, Immediate(source)); }
// Move if the registers are not identical.
void Move(Register target, Register source);
void Move(Operand dst, const Immediate& x);
void Move(Register dst, const Immediate& src);
void Move(Register dst, Smi* src) { Move(dst, Immediate(src)); }
void Move(Register dst, Handle<HeapObject> src);
void Move(Register dst, Register src);
void Move(Operand dst, const Immediate& src);
// Move an immediate into an XMM register.
void Move(XMMRegister dst, uint32_t src);
......@@ -121,11 +119,11 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void Move(XMMRegister dst, float src) { Move(dst, bit_cast<uint32_t>(src)); }
void Move(XMMRegister dst, double src) { Move(dst, bit_cast<uint64_t>(src)); }
void Move(Register dst, Handle<HeapObject> handle);
void Call(Register reg) { call(reg); }
void Call(Handle<Code> target, RelocInfo::Mode rmode) { call(target, rmode); }
void Call(Label* target) { call(target); }
void Call(Handle<Code> code_object, RelocInfo::Mode rmode);
void Jump(Handle<Code> code_object, RelocInfo::Mode rmode);
void RetpolineCall(Register reg);
void RetpolineCall(Address destination, RelocInfo::Mode rmode);
......@@ -224,17 +222,19 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void LoadRoot(Register destination, Heap::RootListIndex index) override;
// TODO(jgruber,v8:6666): Implement embedded builtins.
// Indirect root-relative loads.
void LoadFromConstantsTable(Register destination,
int constant_index) override {
UNREACHABLE();
}
void LoadRootRegisterOffset(Register destination, intptr_t offset) override {
UNREACHABLE();
}
void LoadRootRelative(Register destination, int32_t offset) override {
UNREACHABLE();
}
int constant_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
void LoadRootRelative(Register destination, int32_t offset) override;
void LoadAddress(Register destination, ExternalReference source);
// Wrapper functions to ensure external reference operands produce
// isolate-independent code if needed.
Operand StaticVariable(const ExternalReference& ext);
Operand StaticArray(Register index, ScaleFactor scale,
const ExternalReference& ext);
// Return and drop arguments from stack, where the number of arguments
// may be bigger than 2^16 - 1. Requires a scratch register.
......@@ -695,7 +695,6 @@ class MacroAssembler : public TurboAssembler {
// from the stack, clobbering only the esp register.
void Drop(int element_count);
void Jump(Handle<Code> target, RelocInfo::Mode rmode) { jmp(target, rmode); }
void Pop(Register dst) { pop(dst); }
void Pop(Operand dst) { pop(dst); }
void PushReturnAddressFrom(Register src) { push(src); }
......
......@@ -585,7 +585,7 @@ bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
ExternalReference word_map =
ExternalReference::re_word_character_map(isolate());
__ test_b(current_character(),
Operand::StaticArray(current_character(), times_1, word_map));
masm_->StaticArray(current_character(), times_1, word_map));
BranchOrBacktrack(zero, on_no_match);
return true;
}
......@@ -600,7 +600,7 @@ bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
ExternalReference word_map =
ExternalReference::re_word_character_map(isolate());
__ test_b(current_character(),
Operand::StaticArray(current_character(), times_1, word_map));
masm_->StaticArray(current_character(), times_1, word_map));
BranchOrBacktrack(not_zero, on_no_match);
if (mode_ != LATIN1) {
__ bind(&done);
......@@ -681,7 +681,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
__ mov(ecx, esp);
__ sub(ecx, Operand::StaticVariable(stack_limit));
__ sub(ecx, masm_->StaticVariable(stack_limit));
// Handle it if the stack pointer is already below the stack limit.
__ j(below_equal, &stack_limit_hit);
// Check if there is room for the variable number of registers above
......@@ -1219,7 +1219,7 @@ void RegExpMacroAssemblerIA32::CheckPreemption() {
Label no_preempt;
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
__ cmp(esp, Operand::StaticVariable(stack_limit));
__ cmp(esp, masm_->StaticVariable(stack_limit));
__ j(above, &no_preempt);
SafeCall(&check_preempt_label_);
......@@ -1232,7 +1232,7 @@ void RegExpMacroAssemblerIA32::CheckStackLimit() {
Label no_stack_overflow;
ExternalReference stack_limit =
ExternalReference::address_of_regexp_stack_limit(isolate());
__ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
__ cmp(backtrack_stackpointer(), masm_->StaticVariable(stack_limit));
__ j(above, &no_stack_overflow);
SafeCall(&stack_overflow_label_);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment