Skip to content

Commit 77bbf5f

Browse files
committed
Add support for WASM calls
https://bugs.webkit.org/show_bug.cgi?id=161727 Reviewed by Filip Pizlo and Michael Saboff. JSTests: Add members of the Call category to the WASMOps special group. * wasm/generate-wasmops-header.js: Source/JavaScriptCore: Add support for WASM calls. Since most of the work for this was already done when we added WASM Memory, this is mostly just cleanup work. The main interesting part of this patch is how we link calls to other WASM functions in the same module. Since a WASM callee may not have been compiled by the time the current function has started compilation we don't know what address we need to call to. For each callsite in the compiling function, WASM remembers the CodeLocationCall and the target function index. Once all WASM functions are compiled, each callsite is linked to the appropriate entrypoint. * testWASM.cpp: (runWASMTests): * wasm/WASMB3IRGenerator.cpp: (JSC::WASM::createJSWrapper): (JSC::WASM::parseAndCompile): * wasm/WASMB3IRGenerator.h: * wasm/WASMCallingConvention.cpp: (JSC::WASM::jscCallingConvention): (JSC::WASM::wasmCallingConvention): * wasm/WASMCallingConvention.h: (JSC::WASM::CallingConvention::CallingConvention): (JSC::WASM::CallingConvention::marshallArgumentImpl): (JSC::WASM::CallingConvention::marshallArgument): (JSC::WASM::CallingConvention::loadArguments): (JSC::WASM::CallingConvention::setupCall): (JSC::WASM::CallingConvention::iterate): Deleted. * wasm/WASMFormat.h: * wasm/WASMFunctionParser.h: (JSC::WASM::FunctionParser<Context>::FunctionParser): (JSC::WASM::FunctionParser<Context>::parseBlock): (JSC::WASM::FunctionParser<Context>::parseExpression): * wasm/WASMModuleParser.cpp: (JSC::WASM::ModuleParser::parse): * wasm/WASMOps.h: * wasm/WASMParser.h: (JSC::WASM::Parser::parseVarUInt32): (JSC::WASM::Parser::parseVarUInt64): * wasm/WASMPlan.cpp: (JSC::WASM::Plan::Plan): Source/WTF: Added a new decodeUInt64. Also, added WTF::LEBDecoder namespace. * wtf/LEBDecoder.h: (WTF::LEBDecoder::decodeUInt): (WTF::LEBDecoder::decodeUInt32): (WTF::LEBDecoder::decodeUInt64): (WTF::LEBDecoder::decodeInt32): (decodeUInt32): Deleted. (decodeInt32): Deleted. Canonical link: https://commits.webkit.org/181551@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207671 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent bb4a1bd commit 77bbf5f

16 files changed

Lines changed: 432 additions & 64 deletions

JSTests/ChangeLog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2016-10-20 Keith Miller <keith_miller@apple.com>
2+
3+
Add support for WASM calls
4+
https://bugs.webkit.org/show_bug.cgi?id=161727
5+
6+
Reviewed by Filip Pizlo and Michael Saboff.
7+
8+
Add members of the Call category to the WASMOps special group.
9+
10+
* wasm/generate-wasmops-header.js:
11+
112
2016-10-20 Yusuke Suzuki <utatane.tea@gmail.com>
213

314
[JSC] Drop isEnvironmentRecord type info flag and use JSType information instead

JSTests/wasm/generate-wasmops-header.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function* opcodeMacroizer(filter) {
2929

3030
const defines = [
3131
"#define FOR_EACH_WASM_SPECIAL_OP(macro)",
32-
...opcodeMacroizer(op => op.category === "special"),
32+
...opcodeMacroizer(op => op.category === "special" || op.category === "call"),
3333
"\n\n#define FOR_EACH_WASM_CONTROL_FLOW_OP(macro)",
3434
...opcodeMacroizer(op => op.category === "control"),
3535
"\n\n#define FOR_EACH_WASM_UNARY_OP(macro)",

Source/JavaScriptCore/ChangeLog

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,48 @@
1+
2016-10-20 Keith Miller <keith_miller@apple.com>
2+
3+
Add support for WASM calls
4+
https://bugs.webkit.org/show_bug.cgi?id=161727
5+
6+
Reviewed by Filip Pizlo and Michael Saboff.
7+
8+
Add support for WASM calls. Since most of the work for this was already done when we added
9+
WASM Memory, this is mostly just cleanup work. The main interesting part of this patch is
10+
how we link calls to other WASM functions in the same module. Since a WASM callee may not
11+
have been compiled by the time the current function has started compilation we don't know
12+
what address we need to call to. For each callsite in the compiling function, WASM
13+
remembers the CodeLocationCall and the target function index. Once all WASM functions are
14+
compiled, each callsite is linked to the appropriate entrypoint.
15+
16+
* testWASM.cpp:
17+
(runWASMTests):
18+
* wasm/WASMB3IRGenerator.cpp:
19+
(JSC::WASM::createJSWrapper):
20+
(JSC::WASM::parseAndCompile):
21+
* wasm/WASMB3IRGenerator.h:
22+
* wasm/WASMCallingConvention.cpp:
23+
(JSC::WASM::jscCallingConvention):
24+
(JSC::WASM::wasmCallingConvention):
25+
* wasm/WASMCallingConvention.h:
26+
(JSC::WASM::CallingConvention::CallingConvention):
27+
(JSC::WASM::CallingConvention::marshallArgumentImpl):
28+
(JSC::WASM::CallingConvention::marshallArgument):
29+
(JSC::WASM::CallingConvention::loadArguments):
30+
(JSC::WASM::CallingConvention::setupCall):
31+
(JSC::WASM::CallingConvention::iterate): Deleted.
32+
* wasm/WASMFormat.h:
33+
* wasm/WASMFunctionParser.h:
34+
(JSC::WASM::FunctionParser<Context>::FunctionParser):
35+
(JSC::WASM::FunctionParser<Context>::parseBlock):
36+
(JSC::WASM::FunctionParser<Context>::parseExpression):
37+
* wasm/WASMModuleParser.cpp:
38+
(JSC::WASM::ModuleParser::parse):
39+
* wasm/WASMOps.h:
40+
* wasm/WASMParser.h:
41+
(JSC::WASM::Parser::parseVarUInt32):
42+
(JSC::WASM::Parser::parseVarUInt64):
43+
* wasm/WASMPlan.cpp:
44+
(JSC::WASM::Plan::Plan):
45+
146
2016-10-21 Wenson Hsieh <wenson_hsieh@apple.com>
247

348
Implement InputEvent.getTargetRanges() for the input events spec

Source/JavaScriptCore/testWASM.cpp

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ StaticLock crashLock;
135135
Vector<uint8_t> vector = Vector<uint8_t> init; \
136136
size_t offset = startOffset; \
137137
uint32_t result; \
138-
bool status = decodeUInt32(vector.data(), vector.size(), offset, result); \
138+
bool status = WTF::LEBDecoder::decodeUInt32(vector.data(), vector.size(), offset, result); \
139139
CHECK_EQ(status, expectedStatus); \
140140
if (expectedStatus) { \
141141
CHECK_EQ(result, expectedResult); \
@@ -183,7 +183,7 @@ StaticLock crashLock;
183183
Vector<uint8_t> vector = Vector<uint8_t> init; \
184184
size_t offset = startOffset; \
185185
int32_t result; \
186-
bool status = decodeInt32(vector.data(), vector.size(), offset, result); \
186+
bool status = WTF::LEBDecoder::decodeInt32(vector.data(), vector.size(), offset, result); \
187187
CHECK_EQ(status, expectedStatus); \
188188
if (expectedStatus) { \
189189
int32_t expected = expectedResult; \
@@ -242,6 +242,136 @@ inline JSValue box(uint64_t value)
242242
// For now we inline the test files.
243243
static void runWASMTests()
244244
{
245+
{
246+
// Generated from:
247+
// (module
248+
// (memory 1)
249+
// (func $sum12 (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (result i32) (return (i32.add (get_local 0) (i32.add (get_local 1) (i32.add (get_local 2) (i32.add (get_local 3) (i32.add (get_local 4) (i32.add (get_local 5) (i32.add (get_local 6) (i32.add (get_local 7) (i32.add (get_local 8) (i32.add (get_local 9) (i32.add (get_local 10) (get_local 11))))))))))))))
250+
// (func (export "mult12") (param i32) (result i32) (return (call $sum12 (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0) (get_local 0))))
251+
// )
252+
253+
Vector<uint8_t> vector = {
254+
0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x96, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40,
255+
0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
256+
0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x01, 0x05, 0x83, 0x80,
257+
0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x8a, 0x80, 0x80, 0x80, 0x00, 0x01, 0x06, 0x6d, 0x75,
258+
0x6c, 0x74, 0x31, 0x32, 0x00, 0x01, 0x0a, 0xce, 0x80, 0x80, 0x80, 0x00, 0x02, 0xa6, 0x80, 0x80,
259+
0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x14, 0x02, 0x14, 0x03, 0x14, 0x04, 0x14, 0x05, 0x14,
260+
0x06, 0x14, 0x07, 0x14, 0x08, 0x14, 0x09, 0x14, 0x0a, 0x14, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40,
261+
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x0f, 0x9d, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00,
262+
0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
263+
0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x16, 0x00, 0x09, 0x0f
264+
};
265+
266+
Plan plan(*vm, vector);
267+
if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
268+
dataLogLn("Module failed to compile correctly.");
269+
CRASH();
270+
}
271+
272+
// Test this doesn't crash.
273+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(0) }), 0);
274+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(100) }), 1200);
275+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(1) }), 12);
276+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
277+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
278+
}
279+
280+
{
281+
// Generated from:
282+
// (module
283+
// (memory 1)
284+
// (func $fac (export "fac") (param i64) (result i64)
285+
// (if (i64.eqz (get_local 0))
286+
// (return (i64.const 1))
287+
// )
288+
// (return (i64.mul (get_local 0) (call $fac (i64.sub (get_local 0) (i64.const 1)))))
289+
// )
290+
// )
291+
Vector<uint8_t> vector = {
292+
0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
293+
0x01, 0x02, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80,
294+
0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x66, 0x61, 0x63,
295+
0x00, 0x00, 0x0a, 0x9e, 0x80, 0x80, 0x80, 0x00, 0x01, 0x98, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14,
296+
0x00, 0x11, 0x00, 0x68, 0x03, 0x00, 0x11, 0x01, 0x09, 0x0f, 0x14, 0x00, 0x14, 0x00, 0x11, 0x01,
297+
0x5c, 0x16, 0x00, 0x5d, 0x09, 0x0f
298+
};
299+
300+
Plan plan(*vm, vector);
301+
if (plan.result.size() != 1 || !plan.result[0]) {
302+
dataLogLn("Module failed to compile correctly.");
303+
CRASH();
304+
}
305+
306+
// Test this doesn't crash.
307+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 1);
308+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1);
309+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2) }), 2);
310+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(4) }), 24);
311+
}
312+
313+
{
314+
// Generated from:
315+
// (module
316+
// (memory 1)
317+
// (func (export "double") (param i64) (result i64) (return (call 1 (get_local 0) (get_local 0))))
318+
// (func $sum (param i64) (param i64) (result i64) (return (i64.add (get_local 0) (get_local 1))))
319+
// )
320+
Vector<uint8_t> vector = {
321+
0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40,
322+
0x01, 0x02, 0x01, 0x02, 0x40, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00,
323+
0x02, 0x00, 0x01, 0x05, 0x83, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x07, 0x8a, 0x80, 0x80,
324+
0x80, 0x00, 0x01, 0x06, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x0a, 0x9c, 0x80, 0x80,
325+
0x80, 0x00, 0x02, 0x89, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x16, 0x01, 0x09,
326+
0x0f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x5b, 0x09, 0x0f
327+
};
328+
329+
Plan plan(*vm, vector);
330+
if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
331+
dataLogLn("Module failed to compile correctly.");
332+
CRASH();
333+
}
334+
335+
// Test this doesn't crash.
336+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(0), box(0) }), 0);
337+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(100), box(0) }), 100);
338+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(1), box(15) }), 16);
339+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
340+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 200);
341+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 2);
342+
}
343+
344+
{
345+
// Generated from:
346+
// (module
347+
// (memory 1)
348+
// (func $id (param $value i32) (result i32) (return (get_local $value)))
349+
// (func (export "id-call") (param $value i32) (result i32) (return (call $id (get_local $value))))
350+
// )
351+
Vector<uint8_t> vector = {
352+
0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
353+
0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0x80, 0x80, 0x80, 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x80,
354+
0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x07, 0x69, 0x64,
355+
0x2d, 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x01, 0x0a, 0x97, 0x80, 0x80, 0x80, 0x00, 0x02, 0x85, 0x80,
356+
0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x09, 0x0f, 0x87, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00,
357+
0x16, 0x00, 0x09, 0x0f
358+
};
359+
360+
Plan plan(*vm, vector);
361+
if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
362+
dataLogLn("Module failed to compile correctly.");
363+
CRASH();
364+
}
365+
366+
// Test this doesn't crash.
367+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(0) }), 0);
368+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(100) }), 100);
369+
CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(1) }), 1);
370+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
371+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 100);
372+
CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1);
373+
}
374+
245375
{
246376
// Generated from:
247377
// (module

Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class B3IRGenerator {
170170
typedef Vector<Variable*, 1> ResultList;
171171
static constexpr ExpressionType emptyExpression = nullptr;
172172

173-
B3IRGenerator(Memory*, Procedure&);
173+
B3IRGenerator(Memory*, Procedure&, Vector<UnlinkedCall>& unlinkedCalls);
174174

175175
void addArguments(const Vector<Type>&);
176176
void addLocal(Type, uint32_t);
@@ -198,6 +198,8 @@ class B3IRGenerator {
198198
bool WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const ExpressionList& returnValues);
199199
bool WARN_UNUSED_RETURN endBlock(ControlData&, ExpressionList& expressionStack);
200200

201+
bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const FunctionInformation&, Vector<ExpressionType>& args, ExpressionType& result);
202+
201203
bool isContinuationReachable(ControlData&);
202204

203205
void dump(const Vector<ControlType>& controlStack, const ExpressionList& expressionStack);
@@ -214,13 +216,16 @@ class B3IRGenerator {
214216
Procedure& m_proc;
215217
BasicBlock* m_currentBlock;
216218
Vector<Variable*> m_locals;
219+
// m_unlikedCalls is list of each call site and the function index whose address it should be patched with.
220+
Vector<UnlinkedCall>& m_unlinkedCalls;
217221
GPRReg m_memoryBaseGPR;
218222
GPRReg m_memorySizeGPR;
219223
};
220224

221-
B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure)
225+
B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure, Vector<UnlinkedCall>& unlinkedCalls)
222226
: m_memory(memory)
223227
, m_proc(procedure)
228+
, m_unlinkedCalls(unlinkedCalls)
224229
{
225230
m_currentBlock = m_proc.addBlock();
226231

@@ -231,13 +236,13 @@ B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure)
231236
m_memorySizeGPR = m_memory->pinnedRegisters().sizeRegisters[0].sizeRegister;
232237
for (const PinnedSizeRegisterInfo& info : m_memory->pinnedRegisters().sizeRegisters)
233238
m_proc.pinRegister(info.sizeRegister);
234-
}
235239

236-
m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) {
237-
ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
238-
// FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351
239-
jit.breakpoint();
240-
});
240+
m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) {
241+
ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
242+
// FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351
243+
jit.breakpoint();
244+
});
245+
}
241246
}
242247

243248
void B3IRGenerator::addLocal(Type type, uint32_t count)
@@ -251,7 +256,7 @@ void B3IRGenerator::addArguments(const Vector<Type>& types)
251256
{
252257
ASSERT(!m_locals.size());
253258
m_locals.grow(types.size());
254-
jscCallingConvention().iterate(types, m_proc, m_currentBlock, Origin(),
259+
wasmCallingConvention().loadArguments(types, m_proc, m_currentBlock, Origin(),
255260
[&] (ExpressionType argument, unsigned i) {
256261
Variable* argumentVariable = m_proc.addVariable(argument->type());
257262
m_locals[i] = argumentVariable;
@@ -561,6 +566,32 @@ bool B3IRGenerator::endBlock(ControlData& data, ExpressionList& expressionStack)
561566
return true;
562567
}
563568

569+
bool B3IRGenerator::addCall(unsigned functionIndex, const FunctionInformation& info, Vector<ExpressionType>& args, ExpressionType& result)
570+
{
571+
ASSERT(info.signature->arguments.size() == args.size());
572+
573+
Type returnType = info.signature->returnType;
574+
575+
size_t callIndex = m_unlinkedCalls.size();
576+
m_unlinkedCalls.grow(callIndex + 1);
577+
result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
578+
[&] (PatchpointValue* patchpoint) {
579+
patchpoint->effects.writesPinned = true;
580+
patchpoint->effects.readsPinned = true;
581+
582+
patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
583+
AllowMacroScratchRegisterUsage allowScratch(jit);
584+
585+
CCallHelpers::Call call = jit.call();
586+
587+
jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
588+
m_unlinkedCalls[callIndex] = { linkBuffer.locationOf(call), functionIndex };
589+
});
590+
});
591+
});
592+
return true;
593+
}
594+
564595
bool B3IRGenerator::isContinuationReachable(ControlData& data)
565596
{
566597
// If nothing targets the continuation of the current block then we don't want to create
@@ -642,18 +673,27 @@ static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* sig
642673

643674
// Get our arguments.
644675
Vector<Value*> arguments;
645-
jscCallingConvention().iterate(signature->arguments, proc, block, Origin(), [&] (Value* argument, unsigned) {
676+
jscCallingConvention().loadArguments(signature->arguments, proc, block, Origin(), [&] (Value* argument, unsigned) {
646677
arguments.append(argument);
647678
});
648679

649680
// Move the arguments into place.
650-
Value* result = jscCallingConvention().setupCall(proc, block, Origin(), mainFunction, arguments, toB3Type(signature->returnType), [&] (PatchpointValue* patchpoint) {
681+
Value* result = wasmCallingConvention().setupCall(proc, block, Origin(), arguments, toB3Type(signature->returnType), [&] (PatchpointValue* patchpoint) {
651682
if (memory) {
652683
ASSERT(sizes.size() == memory->pinnedRegisters().sizeRegisters.size());
653684
patchpoint->append(ConstrainedValue(baseMemory, ValueRep::reg(memory->pinnedRegisters().baseMemoryPointer)));
654685
for (unsigned i = 0; i < sizes.size(); ++i)
655686
patchpoint->append(ConstrainedValue(sizes[i], ValueRep::reg(memory->pinnedRegisters().sizeRegisters[i].sizeRegister)));
656687
}
688+
689+
patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
690+
AllowMacroScratchRegisterUsage allowScratch(jit);
691+
692+
CCallHelpers::Call call = jit.call();
693+
jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
694+
linkBuffer.link(call, FunctionPtr(mainFunction.executableAddress()));
695+
});
696+
});
657697
});
658698

659699
// Return the result, if needed.
@@ -665,11 +705,13 @@ static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* sig
665705
return std::make_unique<Compilation>(vm, proc);
666706
}
667707

668-
std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, Vector<uint8_t>& source, Memory* memory, FunctionInformation info, unsigned optLevel)
708+
std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, Vector<uint8_t>& source, Memory* memory, FunctionInformation info, const Vector<FunctionInformation>& functions, unsigned optLevel)
669709
{
710+
auto result = std::make_unique<FunctionCompilation>();
711+
670712
Procedure procedure;
671-
B3IRGenerator context(memory, procedure);
672-
FunctionParser<B3IRGenerator> parser(context, source, info);
713+
B3IRGenerator context(memory, procedure, result->unlinkedCalls);
714+
FunctionParser<B3IRGenerator> parser(context, source, info, functions);
673715
if (!parser.parse())
674716
RELEASE_ASSERT_NOT_REACHED();
675717

@@ -679,7 +721,6 @@ std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, Vector<uint8_t>& so
679721
fixSSA(procedure);
680722
if (verbose)
681723
dataLog("Post SSA: ", procedure);
682-
auto result = std::make_unique<FunctionCompilation>();
683724

684725
result->code = std::make_unique<Compilation>(vm, procedure, optLevel);
685726
result->jsEntryPoint = createJSWrapper(vm, info.signature, result->code->code(), memory);

Source/JavaScriptCore/wasm/WASMB3IRGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ namespace JSC { namespace WASM {
3737

3838
class Memory;
3939

40-
std::unique_ptr<FunctionCompilation> parseAndCompile(VM&, Vector<uint8_t>&, Memory*, FunctionInformation, unsigned optLevel = 1);
40+
std::unique_ptr<FunctionCompilation> parseAndCompile(VM&, Vector<uint8_t>&, Memory*, FunctionInformation, const Vector<FunctionInformation>&, unsigned optLevel = 1);
4141

4242
} } // namespace JSC::WASM
4343

0 commit comments

Comments
 (0)