Skip to content

Commit 3b157ba

Browse files
committed
codegen: more compliant func constr/method flags
test262: 57.02% (+0.27) | πŸ§ͺ 50372 | 🀠 28723 (+138) | ❌ 6997 (-25) | πŸ’€ 13634 (-111) | πŸ—οΈ 31 | πŸ’₯ 263 | ⏰ 7 (-2) | πŸ“ 717
1 parent 62c5f51 commit 3b157ba

File tree

5 files changed

+25
-10
lines changed

5 files changed

+25
-10
lines changed

β€Žcompiler/assemble.js

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
141141
if (length == null) {
142142
length = func.params.length;
143143
if (func.constr) length -= 4;
144+
if (func.method) length -= 2;
144145
if (!func.internal || func.typedParams) length = Math.floor(length / 2);
145146

146147
// remove _this from internal prototype funcs

β€Žcompiler/codegen.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const funcRef = func => {
9393
}
9494

9595
const wasm = [];
96-
const offset = func.constr ? 0 : 4;
96+
const offset = func.constr ? 0 : (func.method ? 2 : 4);
9797
for (let i = 0; i < func.params.length; i++) {
9898
if (func.internal && func.name.includes('_prototype_') && i < 2) {
9999
// special case: use real this for prototype internals
@@ -456,7 +456,7 @@ const lookup = (scope, name, failEarly = false) => {
456456
// todo: not compliant
457457
let len = countLength(scope);
458458
const names = new Array(len);
459-
const off = scope.constr ? 4 : 0;
459+
const off = scope.constr ? 4 : (scope.method ? 2 : 0);
460460
for (const x in scope.locals) {
461461
const i = scope.locals[x].idx - off;
462462
if (i >= 0 && i % 2 === 0 && i < len * 2) {
@@ -1716,7 +1716,7 @@ const getNodeType = (scope, node) => {
17161716

17171717
if (node.type === 'ThisExpression') {
17181718
if (scope.overrideThisType) return scope.overrideThisType;
1719-
if (!scope.constr) return getType(scope, 'globalThis');
1719+
if (!scope.constr && !scope.method) return getType(scope, 'globalThis');
17201720
return [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ];
17211721
}
17221722

@@ -2636,6 +2636,11 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
26362636
paramOffset += 4;
26372637
}
26382638

2639+
if (func && func.method) {
2640+
out.push(...(decl._thisWasm ?? createThisArg(scope, decl)));
2641+
paramOffset += 2;
2642+
}
2643+
26392644
if (func && args.length < paramCount) {
26402645
// too little args, push undefineds
26412646
const underflow = paramCount - (func.hasRestArgument ? 1 : 0) - args.length;
@@ -2720,7 +2725,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
27202725
const generateThis = (scope, decl) => {
27212726
if (scope.overrideThis) return scope.overrideThis;
27222727

2723-
if (!scope.constr) {
2728+
if (!scope.constr && !scope.method) {
27242729
// this in a non-constructor context is a reference to globalThis
27252730
return [
27262731
...generate(scope, { type: 'Identifier', name: 'globalThis' })
@@ -5527,7 +5532,10 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
55275532

55285533
for (const x of decl.properties) {
55295534
// method, shorthand are made into useful values by parser for us :)
5530-
let { type, argument, computed, kind, value } = x;
5535+
let { type, argument, computed, kind, value, method } = x;
5536+
5537+
// tag function as not a constructor
5538+
if (method) value._method = true;
55315539

55325540
if (type === 'SpreadElement') {
55335541
out.push(
@@ -5620,6 +5628,7 @@ const countParams = (func, name = undefined) => {
56205628
name ??= func.name;
56215629
let params = func.params.length;
56225630
if (func.constr) params -= 4;
5631+
if (func.method) params -= 2;
56235632
if (!func.internal || builtinFuncs[name]?.typedParams) params = Math.floor(params / 2);
56245633

56255634
return func.argc = params;
@@ -6123,6 +6132,9 @@ const generateClass = (scope, decl) => {
61236132
let { type, value, kind, static: _static, computed } = x;
61246133
if (kind === 'constructor') continue;
61256134

6135+
// tag function as not a constructor
6136+
if (type === 'MethodDefinition') value._method = true;
6137+
61266138
if (type === 'StaticBlock') {
61276139
// todo: make this more compliant
61286140
out.push(
@@ -6448,7 +6460,8 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
64486460
name,
64496461
index: currentFuncIndex++,
64506462
arrow,
6451-
constr: !arrow && !decl.generator && !decl.async,
6463+
constr: !arrow && !decl.generator && !decl.async && !decl._method, // constructable
6464+
method: decl._method || decl.generator || decl.async, // has this but not constructable
64526465
async: decl.async,
64536466
subclass: decl._subclass, _onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
64546467
strict: scope.strict || decl.strict,
@@ -6679,6 +6692,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
66796692

66806693
const args = [];
66816694
if (func.constr) args.push({ name: '#newtarget' }, { name: '#this' });
6695+
if (func.method) args.push({ name: '#this' });
66826696

66836697
let jsLength = 0;
66846698
for (let i = 0; i < params.length; i++) {
@@ -6719,7 +6733,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
67196733
args.push({ name, def, destr, type: typedInput && params[i].typeAnnotation });
67206734
}
67216735

6722-
func.params = new Array((params.length + (func.constr ? 2 : 0)) * 2).fill(0).map((_, i) => i % 2 ? Valtype.i32 : valtypeBinary);
6736+
func.params = new Array((params.length + (func.constr ? 2 : (func.method ? 1 : 0))) * 2).fill(0).map((_, i) => i % 2 ? Valtype.i32 : valtypeBinary);
67236737
func.jsLength = jsLength;
67246738

67256739
// force generate for main

β€Žpackage.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "porffor",
33
"description": "An ahead-of-time JavaScript compiler",
4-
"version": "0.56.0",
4+
"version": "0.56.1",
55
"author": "Oliver Medhurst <[email protected]>",
66
"license": "MIT",
77
"scripts": {},

β€Žrunner/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env node
22
import fs from 'node:fs';
3-
globalThis.version = '0.56.0';
3+
globalThis.version = '0.56.1';
44

55
// deno compat
66
if (typeof process === 'undefined' && typeof Deno !== 'undefined') {

β€Žtest262/history.json

+1-1
Large diffs are not rendered by default.

0 commit comments

Comments
Β (0)