Commit edfcba04 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Introduce builtin for grow_memory

This CL adds a builtin which receives an int32 argument and returns the
int32 result. Internally, it checks whether the argument is in the
valid smi range, then calls the runtime function with the smi argument
and converts the return value back from smi to int32.
This saves a lot of code in the wasm TF builder and in Liftoff.

R=mstarzinger@chromium.org

Bug: v8:6600
Change-Id: Icddcb020eae74c767a75090feb4939275432c007
Reviewed-on: https://chromium-review.googlesource.com/1107711
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53946}
parent 7da6adcb
...@@ -1205,8 +1205,9 @@ namespace internal { ...@@ -1205,8 +1205,9 @@ namespace internal {
TFC(WasmAllocateHeapNumber, AllocateHeapNumber, 1) \ TFC(WasmAllocateHeapNumber, AllocateHeapNumber, 1) \
TFC(WasmArgumentsAdaptor, ArgumentAdaptor, 1) \ TFC(WasmArgumentsAdaptor, ArgumentAdaptor, 1) \
TFC(WasmCallJavaScript, CallTrampoline, 1) \ TFC(WasmCallJavaScript, CallTrampoline, 1) \
TFC(WasmToNumber, TypeConversion, 1) \ TFC(WasmGrowMemory, WasmGrowMemory, 1) \
TFS(WasmStackGuard) \ TFS(WasmStackGuard) \
TFC(WasmToNumber, TypeConversion, 1) \
TFS(ThrowWasmTrapUnreachable) \ TFS(ThrowWasmTrapUnreachable) \
TFS(ThrowWasmTrapMemOutOfBounds) \ TFS(ThrowWasmTrapMemOutOfBounds) \
TFS(ThrowWasmTrapDivByZero) \ TFS(ThrowWasmTrapDivByZero) \
......
...@@ -21,8 +21,7 @@ class WasmBuiltinsAssembler : public CodeStubAssembler { ...@@ -21,8 +21,7 @@ class WasmBuiltinsAssembler : public CodeStubAssembler {
} }
TNode<Code> LoadBuiltinFromFrame(Builtins::Name id) { TNode<Code> LoadBuiltinFromFrame(Builtins::Name id) {
TNode<Object> instance = UncheckedCast<Object>( TNode<Object> instance = LoadInstanceFromFrame();
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
TNode<IntPtrT> roots = UncheckedCast<IntPtrT>( TNode<IntPtrT> roots = UncheckedCast<IntPtrT>(
Load(MachineType::Pointer(), instance, Load(MachineType::Pointer(), instance,
IntPtrConstant(WasmInstanceObject::kRootsArrayAddressOffset - IntPtrConstant(WasmInstanceObject::kRootsArrayAddressOffset -
...@@ -32,6 +31,22 @@ class WasmBuiltinsAssembler : public CodeStubAssembler { ...@@ -32,6 +31,22 @@ class WasmBuiltinsAssembler : public CodeStubAssembler {
IntPtrConstant(Heap::roots_to_builtins_offset() + id * kPointerSize))); IntPtrConstant(Heap::roots_to_builtins_offset() + id * kPointerSize)));
return target; return target;
} }
TNode<Object> LoadInstanceFromFrame() {
return UncheckedCast<Object>(
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
}
TNode<Code> LoadCEntryFromInstance(TNode<Object> instance) {
return UncheckedCast<Code>(
Load(MachineType::AnyTagged(), instance,
IntPtrConstant(WasmInstanceObject::kCEntryStubOffset -
kHeapObjectTag)));
}
TNode<Code> LoadCEntryFromFrame() {
return LoadCEntryFromInstance(LoadInstanceFromFrame());
}
}; };
TF_BUILTIN(WasmAllocateHeapNumber, WasmBuiltinsAssembler) { TF_BUILTIN(WasmAllocateHeapNumber, WasmBuiltinsAssembler) {
...@@ -67,27 +82,40 @@ TF_BUILTIN(WasmToNumber, WasmBuiltinsAssembler) { ...@@ -67,27 +82,40 @@ TF_BUILTIN(WasmToNumber, WasmBuiltinsAssembler) {
TailCallStub(TypeConversionDescriptor(), target, context, argument); TailCallStub(TypeConversionDescriptor(), target, context, argument);
} }
TF_BUILTIN(WasmStackGuard, CodeStubAssembler) { TF_BUILTIN(WasmStackGuard, WasmBuiltinsAssembler) {
TNode<Object> instance = UncheckedCast<Object>( TNode<Code> centry = LoadCEntryFromFrame();
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
TNode<Code> centry = UncheckedCast<Code>(Load(
MachineType::AnyTagged(), instance,
IntPtrConstant(WasmInstanceObject::kCEntryStubOffset - kHeapObjectTag)));
TailCallRuntimeWithCEntry(Runtime::kWasmStackGuard, centry, TailCallRuntimeWithCEntry(Runtime::kWasmStackGuard, centry,
NoContextConstant()); NoContextConstant());
} }
#define DECLARE_ENUM(name) \ TF_BUILTIN(WasmGrowMemory, WasmBuiltinsAssembler) {
TF_BUILTIN(ThrowWasm##name, CodeStubAssembler) { \ TNode<Int32T> num_pages =
TNode<Object> instance = UncheckedCast<Object>( \ UncheckedCast<Int32T>(Parameter(Descriptor::kNumPages));
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset)); \ Label num_pages_out_of_range(this, Label::kDeferred);
TNode<Code> centry = UncheckedCast<Code>( \
Load(MachineType::AnyTagged(), instance, \ TNode<BoolT> num_pages_fits_in_smi =
IntPtrConstant(WasmInstanceObject::kCEntryStubOffset - \ IsValidPositiveSmi(ChangeInt32ToIntPtr(num_pages));
kHeapObjectTag))); \ GotoIfNot(num_pages_fits_in_smi, &num_pages_out_of_range);
int message_id = wasm::WasmOpcodes::TrapReasonToMessageId(wasm::k##name); \
TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, \ TNode<Smi> num_pages_smi = SmiFromInt32(num_pages);
NoContextConstant(), SmiConstant(message_id)); \ TNode<Object> instance = LoadInstanceFromFrame();
TNode<Code> centry = LoadCEntryFromInstance(instance);
TNode<Smi> ret_smi = UncheckedCast<Smi>(
CallRuntimeWithCEntry(Runtime::kWasmGrowMemory, centry,
NoContextConstant(), instance, num_pages_smi));
TNode<Int32T> ret = SmiToInt32(ret_smi);
ReturnRaw(ret);
BIND(&num_pages_out_of_range);
ReturnRaw(Int32Constant(-1));
}
#define DECLARE_ENUM(name) \
TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \
TNode<Code> centry = LoadCEntryFromFrame(); \
int message_id = wasm::WasmOpcodes::TrapReasonToMessageId(wasm::k##name); \
TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, \
NoContextConstant(), SmiConstant(message_id)); \
} }
FOREACH_WASM_TRAPREASON(DECLARE_ENUM) FOREACH_WASM_TRAPREASON(DECLARE_ENUM)
#undef DECLARE_ENUM #undef DECLARE_ENUM
......
...@@ -409,6 +409,10 @@ void CodeAssembler::ReturnIf(Node* condition, Node* value) { ...@@ -409,6 +409,10 @@ void CodeAssembler::ReturnIf(Node* condition, Node* value) {
Bind(&if_continue); Bind(&if_continue);
} }
void CodeAssembler::ReturnRaw(Node* value) {
return raw_assembler()->Return(value);
}
void CodeAssembler::DebugAbort(Node* message) { void CodeAssembler::DebugAbort(Node* message) {
raw_assembler()->DebugAbort(message); raw_assembler()->DebugAbort(message);
} }
...@@ -1072,16 +1076,22 @@ class NodeArray { ...@@ -1072,16 +1076,22 @@ class NodeArray {
TNode<Object> CodeAssembler::CallRuntimeImpl( TNode<Object> CodeAssembler::CallRuntimeImpl(
Runtime::FunctionId function, TNode<Object> context, Runtime::FunctionId function, TNode<Object> context,
std::initializer_list<TNode<Object>> args) { std::initializer_list<TNode<Object>> args) {
int result_size = Runtime::FunctionForId(function)->result_size;
TNode<Code> centry =
HeapConstant(CodeFactory::RuntimeCEntry(isolate(), result_size));
return CallRuntimeWithCEntryImpl(function, centry, context, args);
}
TNode<Object> CodeAssembler::CallRuntimeWithCEntryImpl(
Runtime::FunctionId function, TNode<Code> centry, TNode<Object> context,
std::initializer_list<TNode<Object>> args) {
constexpr size_t kMaxNumArgs = 6; constexpr size_t kMaxNumArgs = 6;
DCHECK_GE(kMaxNumArgs, args.size()); DCHECK_GE(kMaxNumArgs, args.size());
int argc = static_cast<int>(args.size()); int argc = static_cast<int>(args.size());
auto call_descriptor = Linkage::GetRuntimeCallDescriptor( auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
zone(), function, argc, Operator::kNoProperties, zone(), function, argc, Operator::kNoProperties,
CallDescriptor::kNoFlags); CallDescriptor::kNoFlags);
int return_count = static_cast<int>(call_descriptor->ReturnCount());
Node* centry =
HeapConstant(CodeFactory::RuntimeCEntry(isolate(), return_count));
Node* ref = ExternalConstant(ExternalReference::Create(function)); Node* ref = ExternalConstant(ExternalReference::Create(function));
Node* arity = Int32Constant(argc); Node* arity = Int32Constant(argc);
......
...@@ -749,6 +749,8 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -749,6 +749,8 @@ class V8_EXPORT_PRIVATE CodeAssembler {
void ReturnIf(Node* condition, Node* value); void ReturnIf(Node* condition, Node* value);
void ReturnRaw(Node* value);
void DebugAbort(Node* message); void DebugAbort(Node* message);
void DebugBreak(); void DebugBreak();
void Unreachable(); void Unreachable();
...@@ -987,6 +989,14 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -987,6 +989,14 @@ class V8_EXPORT_PRIVATE CodeAssembler {
{implicit_cast<SloppyTNode<Object>>(args)...}); {implicit_cast<SloppyTNode<Object>>(args)...});
} }
template <class... TArgs>
TNode<Object> CallRuntimeWithCEntry(Runtime::FunctionId function,
TNode<Code> centry,
SloppyTNode<Object> context,
TArgs... args) {
return CallRuntimeWithCEntryImpl(function, centry, context, {args...});
}
template <class... TArgs> template <class... TArgs>
void TailCallRuntime(Runtime::FunctionId function, void TailCallRuntime(Runtime::FunctionId function,
SloppyTNode<Object> context, TArgs... args) { SloppyTNode<Object> context, TArgs... args) {
...@@ -1007,7 +1017,7 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -1007,7 +1017,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
void TailCallRuntimeWithCEntry(Runtime::FunctionId function, void TailCallRuntimeWithCEntry(Runtime::FunctionId function,
TNode<Code> centry, TNode<Object> context, TNode<Code> centry, TNode<Object> context,
TArgs... args) { TArgs... args) {
int argc = static_cast<int>(sizeof...(args)); int argc = sizeof...(args);
TNode<Int32T> arity = Int32Constant(argc); TNode<Int32T> arity = Int32Constant(argc);
return TailCallRuntimeWithCEntryImpl( return TailCallRuntimeWithCEntryImpl(
function, arity, centry, context, function, arity, centry, context,
...@@ -1193,6 +1203,10 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -1193,6 +1203,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
TNode<Object> context, TNode<Object> context,
std::initializer_list<TNode<Object>> args); std::initializer_list<TNode<Object>> args);
TNode<Object> CallRuntimeWithCEntryImpl(
Runtime::FunctionId function, TNode<Code> centry, TNode<Object> context,
std::initializer_list<TNode<Object>> args);
void TailCallRuntimeImpl(Runtime::FunctionId function, TNode<Int32T> arity, void TailCallRuntimeImpl(Runtime::FunctionId function, TNode<Int32T> arity,
TNode<Object> context, TNode<Object> context,
std::initializer_list<TNode<Object>> args); std::initializer_list<TNode<Object>> args);
......
...@@ -2009,28 +2009,26 @@ Node* WasmGraphBuilder::BuildCcallConvertFloat(Node* input, ...@@ -2009,28 +2009,26 @@ Node* WasmGraphBuilder::BuildCcallConvertFloat(Node* input,
Node* WasmGraphBuilder::GrowMemory(Node* input) { Node* WasmGraphBuilder::GrowMemory(Node* input) {
SetNeedsStackCheck(); SetNeedsStackCheck();
Diamond check_input_range(
graph(), mcgraph()->common(),
graph()->NewNode(mcgraph()->machine()->Uint32LessThanOrEqual(), input,
mcgraph()->Uint32Constant(FLAG_wasm_max_mem_pages)),
BranchHint::kTrue);
check_input_range.Chain(*control_);
Node* parameters[] = {BuildChangeUint31ToSmi(input)};
Node* old_effect = *effect_;
*control_ = check_input_range.if_true;
Node* call = BuildCallToRuntime(Runtime::kWasmGrowMemory, parameters,
arraysize(parameters));
Node* result = BuildChangeSmiToInt32(call); WasmGrowMemoryDescriptor interface_descriptor;
auto call_descriptor = Linkage::GetStubCallDescriptor(
mcgraph()->zone(), // zone
interface_descriptor, // descriptor
interface_descriptor.GetStackParameterCount(), // stack parameter count
CallDescriptor::kNoFlags, // flags
Operator::kNoProperties, // properties
Linkage::kNoContext, // context specification
StubCallMode::kCallWasmRuntimeStub); // stub call mode
// A direct call to a wasm runtime stub defined in this module.
// Just encode the stub index. This will be patched at relocation.
Node* call_target = mcgraph()->RelocatableIntPtrConstant(
wasm::WasmCode::kWasmGrowMemory, RelocInfo::WASM_STUB_CALL);
Node* call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
call_target, input, *effect_, *control_);
result = check_input_range.Phi(MachineRepresentation::kWord32, result, *effect_ = call;
mcgraph()->Int32Constant(-1)); *control_ = call;
*effect_ = graph()->NewNode(mcgraph()->common()->EffectPhi(2), *effect_, return call;
old_effect, check_input_range.merge);
*control_ = check_input_range.merge;
return result;
} }
uint32_t WasmGraphBuilder::GetExceptionEncodedSize( uint32_t WasmGraphBuilder::GetExceptionEncodedSize(
......
...@@ -460,14 +460,16 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, ...@@ -460,14 +460,16 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
iterator->isolate()->wasm_engine()->code_manager()->LookupCode(pc); iterator->isolate()->wasm_engine()->code_manager()->LookupCode(pc);
if (wasm_code != nullptr) { if (wasm_code != nullptr) {
switch (wasm_code->kind()) { switch (wasm_code->kind()) {
case wasm::WasmCode::kInterpreterEntry:
return WASM_INTERPRETER_ENTRY;
case wasm::WasmCode::kFunction: case wasm::WasmCode::kFunction:
return WASM_COMPILED; return WASM_COMPILED;
case wasm::WasmCode::kLazyStub:
return WASM_COMPILE_LAZY;
case wasm::WasmCode::kWasmToJsWrapper: case wasm::WasmCode::kWasmToJsWrapper:
return WASM_TO_JS; return WASM_TO_JS;
case wasm::WasmCode::kLazyStub:
return WASM_COMPILE_LAZY;
case wasm::WasmCode::kRuntimeStub:
return STUB;
case wasm::WasmCode::kInterpreterEntry:
return WASM_INTERPRETER_ENTRY;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -269,8 +269,10 @@ void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific( ...@@ -269,8 +269,10 @@ void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void WasmGrowMemoryDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -70,6 +70,7 @@ namespace internal { ...@@ -70,6 +70,7 @@ namespace internal {
V(ResumeGenerator) \ V(ResumeGenerator) \
V(FrameDropperTrampoline) \ V(FrameDropperTrampoline) \
V(RunMicrotasks) \ V(RunMicrotasks) \
V(WasmGrowMemory) \
BUILTIN_LIST_TFS(V) BUILTIN_LIST_TFS(V)
class V8_EXPORT_PRIVATE CallInterfaceDescriptorData { class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
...@@ -948,6 +949,14 @@ class RunMicrotasksDescriptor final : public CallInterfaceDescriptor { ...@@ -948,6 +949,14 @@ class RunMicrotasksDescriptor final : public CallInterfaceDescriptor {
DECLARE_DEFAULT_DESCRIPTOR(RunMicrotasksDescriptor, CallInterfaceDescriptor) DECLARE_DEFAULT_DESCRIPTOR(RunMicrotasksDescriptor, CallInterfaceDescriptor)
}; };
class WasmGrowMemoryDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT(1 /* result size */, kNumPages)
DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::Int32() /* result */,
MachineType::Int32() /* kNumPages */)
DECLARE_DESCRIPTOR(WasmGrowMemoryDescriptor, CallInterfaceDescriptor)
};
#define DEFINE_TFS_BUILTIN_DESCRIPTOR(Name, ...) \ #define DEFINE_TFS_BUILTIN_DESCRIPTOR(Name, ...) \
class Name##Descriptor : public CallInterfaceDescriptor { \ class Name##Descriptor : public CallInterfaceDescriptor { \
public: \ public: \
......
...@@ -67,10 +67,11 @@ class ClearThreadInWasmScope { ...@@ -67,10 +67,11 @@ class ClearThreadInWasmScope {
RUNTIME_FUNCTION(Runtime_WasmGrowMemory) { RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(2, args.length());
CONVERT_UINT32_ARG_CHECKED(delta_pages, 0); CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
Handle<WasmInstanceObject> instance(GetWasmInstanceOnStackTop(isolate), // {delta_pages} is checked to be a positive smi in the WasmGrowMemory builtin
isolate); // which calls this runtime function.
CONVERT_UINT32_ARG_CHECKED(delta_pages, 1);
// This runtime function is always being called from wasm code. // This runtime function is always being called from wasm code.
ClearThreadInWasmScope flag_scope(true); ClearThreadInWasmScope flag_scope(true);
......
...@@ -576,7 +576,7 @@ namespace internal { ...@@ -576,7 +576,7 @@ namespace internal {
F(WasmExceptionGetElement, 1, 1) \ F(WasmExceptionGetElement, 1, 1) \
F(WasmExceptionSetElement, 2, 1) \ F(WasmExceptionSetElement, 2, 1) \
F(WasmGetExceptionRuntimeId, 0, 1) \ F(WasmGetExceptionRuntimeId, 0, 1) \
F(WasmGrowMemory, 1, 1) \ F(WasmGrowMemory, 2, 1) \
F(WasmRunInterpreter, 2, 1) \ F(WasmRunInterpreter, 2, 1) \
F(WasmStackGuard, 0, 1) \ F(WasmStackGuard, 0, 1) \
F(WasmThrow, 0, 1) \ F(WasmThrow, 0, 1) \
......
...@@ -1590,39 +1590,6 @@ class LiftoffCompiler { ...@@ -1590,39 +1590,6 @@ class LiftoffCompiler {
__ PushRegister(kWasmI32, mem_size); __ PushRegister(kWasmI32, mem_size);
} }
void Int32ToSmi(LiftoffRegister dst, Register src, Register scratch) {
constexpr int kTotalSmiShift = kSmiTagSize + kSmiShiftSize;
// TODO(clemensh): Shift by immediate directly.
if (SmiValuesAre32Bits()) {
__ LoadConstant(LiftoffRegister(scratch),
WasmValue(int64_t{kTotalSmiShift}));
__ emit_i64_shl(dst, LiftoffRegister(src), scratch);
} else {
DCHECK(SmiValuesAre31Bits());
__ LoadConstant(LiftoffRegister(scratch),
WasmValue(int32_t{kTotalSmiShift}));
__ emit_i32_shl(dst.gp(), src, scratch);
if (kPointerSize == kInt64Size) {
__ emit_i32_to_intptr(dst.gp(), dst.gp());
}
}
}
void SmiToInt32(Register dst, LiftoffRegister src, Register scratch) {
constexpr int kTotalSmiShift = kSmiTagSize + kSmiShiftSize;
// TODO(clemensh): Shift by immediate directly.
if (SmiValuesAre32Bits()) {
__ LoadConstant(LiftoffRegister(scratch),
WasmValue(int64_t{kTotalSmiShift}));
__ emit_i64_shr(LiftoffRegister(dst), src, scratch);
} else {
DCHECK(SmiValuesAre31Bits());
__ LoadConstant(LiftoffRegister(scratch),
WasmValue(int32_t{kTotalSmiShift}));
__ emit_i32_sar(dst, src.gp(), scratch);
}
}
void GrowMemory(Decoder* decoder, const Value& value, Value* result_val) { void GrowMemory(Decoder* decoder, const Value& value, Value* result_val) {
// Pop the input, then spill all cache registers to make the runtime call. // Pop the input, then spill all cache registers to make the runtime call.
LiftoffRegList pinned; LiftoffRegList pinned;
...@@ -1635,28 +1602,23 @@ class LiftoffCompiler { ...@@ -1635,28 +1602,23 @@ class LiftoffCompiler {
"complex code here otherwise)"); "complex code here otherwise)");
LiftoffRegister result = pinned.set(LiftoffRegister(kGpReturnReg)); LiftoffRegister result = pinned.set(LiftoffRegister(kGpReturnReg));
LiftoffRegister tmp_const = WasmGrowMemoryDescriptor descriptor;
pinned.set(__ cache_state()->unused_register(kGpReg, pinned)); DCHECK_EQ(0, descriptor.GetStackParameterCount());
DCHECK_EQ(1, descriptor.GetRegisterParameterCount());
Label done; DCHECK_EQ(ValueTypes::MachineTypeFor(kWasmI32),
Label do_runtime_call; descriptor.GetParameterType(0));
// TODO(clemensh): Compare to immediate directly.
__ LoadConstant(tmp_const, WasmValue(uint32_t{FLAG_wasm_max_mem_pages})); Register param_reg = descriptor.GetRegisterParameter(0);
__ emit_cond_jump(kUnsignedLessEqual, &do_runtime_call, kWasmI32, if (input.gp() != param_reg) __ Move(param_reg, input.gp(), kWasmI32);
input.gp(), tmp_const.gp());
__ LoadConstant(result, WasmValue(int32_t{-1})); __ CallRuntimeStub(wasm::WasmCode::kWasmGrowMemory);
__ emit_jump(&done); safepoint_table_builder_.DefineSafepoint(asm_, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
// TODO(clemensh): Introduce new builtin for smi-conversion, runtime call,
// and conversion back. Use in TF and here. if (kReturnRegister0 != result.gp()) {
__ bind(&do_runtime_call); __ Move(result.gp(), kReturnRegister0, kWasmI32);
LiftoffRegister input_smi = input; }
Int32ToSmi(input_smi, input.gp(), tmp_const.gp());
Register args[] = {input_smi.gp()};
GenerateRuntimeCall(Runtime::kWasmGrowMemory, arraysize(args), args);
SmiToInt32(result.gp(), result, tmp_const.gp());
__ bind(&done);
__ PushRegister(kWasmI32, result); __ PushRegister(kWasmI32, result);
} }
......
...@@ -36,6 +36,7 @@ struct WasmModule; ...@@ -36,6 +36,7 @@ struct WasmModule;
V(WasmAllocateHeapNumber) \ V(WasmAllocateHeapNumber) \
V(WasmArgumentsAdaptor) \ V(WasmArgumentsAdaptor) \
V(WasmCallJavaScript) \ V(WasmCallJavaScript) \
V(WasmGrowMemory) \
V(WasmStackGuard) \ V(WasmStackGuard) \
V(WasmToNumber) \ V(WasmToNumber) \
V(DoubleToI) V(DoubleToI)
......
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