Skip to content

Commit b77ecf1

Browse files
committed
Merge remote-tracking branch 'origin/master' into release
2 parents 026073c + d11db68 commit b77ecf1

File tree

65 files changed

+33503
-78059
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+33503
-78059
lines changed

Diff for: cli/asc.js

+1
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ exports.main = function main(argv, options, callback) {
224224
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
225225
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
226226
assemblyscript.setNoUnsafe(compilerOptions, args.noUnsafe);
227+
assemblyscript.setPedantic(compilerOptions, args.pedantic);
227228

228229
// Initialize default aliases
229230
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");

Diff for: cli/asc.json

+5
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@
224224
"description": "Specifies the path to a custom transform to 'require'.",
225225
"type": "S"
226226
},
227+
"pedantic": {
228+
"description": "Make yourself sad for no good reason.",
229+
"type": "b",
230+
"default": false
231+
},
227232
"traceResolution": {
228233
"description": "Enables tracing of package resolution.",
229234
"type": "b",

Diff for: package-lock.json

+29-35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+6-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"assemblyscript",
99
"wasm"
1010
],
11-
"version": "0.8.1",
11+
"version": "0.9.0",
1212
"author": "Daniel Wirtz <[email protected]>",
1313
"contributors": [],
1414
"license": "Apache-2.0",
@@ -21,24 +21,23 @@
2121
"url": "https://github.com/AssemblyScript/assemblyscript/issues"
2222
},
2323
"dependencies": {
24-
"binaryen": "90.0.0-nightly.20200101",
24+
"binaryen": "90.0.0-nightly.20200111",
2525
"long": "^4.0.0",
2626
"source-map-support": "^0.5.16",
2727
"ts-node": "^6.2.0"
2828
},
2929
"devDependencies": {
30-
"@types/node": "^12.12.17",
30+
"@types/node": "^13.5.0",
3131
"browser-process-hrtime": "^1.0.0",
32-
"diff": "^4.0.1",
32+
"diff": "^4.0.2",
3333
"glob": "^7.1.6",
3434
"physical-cpu-count": "^2.0.0",
3535
"source-map-support": "^0.5.16",
3636
"ts-loader": "^6.2.1",
3737
"ts-node": "^6.2.0",
3838
"tslint": "^5.20.1",
39-
"typedoc-plugin-external-module-name": "^2.1.0",
40-
"typescript": "^3.7.3",
41-
"webpack": "^4.41.3",
39+
"typescript": "^3.7.5",
40+
"webpack": "^4.41.5",
4241
"webpack-cli": "^3.3.10"
4342
},
4443
"main": "index.js",

Diff for: src/builtins.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ import {
6363
Field,
6464
Global,
6565
DecoratorFlags,
66-
Element
66+
Element,
67+
Class
6768
} from "./program";
6869

6970
import {
@@ -4733,7 +4734,8 @@ export function compileVisitGlobals(compiler: Compiler): void {
47334734
var nativeSizeType = compiler.options.nativeSizeType;
47344735
var visitInstance = assert(compiler.program.visitInstance);
47354736

4736-
compiler.compileFunction(visitInstance);
4737+
// this function is @lazy: make sure it exists
4738+
compiler.compileFunction(visitInstance, true);
47374739

47384740
for (let element of compiler.program.elementsByName.values()) {
47394741
if (element.kind != ElementKind.GLOBAL) continue;
@@ -4794,6 +4796,9 @@ export function compileVisitMembers(compiler: Compiler): void {
47944796
var blocks = new Array<RelooperBlockRef>();
47954797
var relooper = Relooper.create(module);
47964798

4799+
// this function is @lazy: make sure it exists
4800+
compiler.compileFunction(visitInstance, true);
4801+
47974802
var outer = relooper.addBlockWithSwitch(
47984803
module.nop(),
47994804
module.load(nativeSizeSize, false,

Diff for: src/compiler.ts

+66-9
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ export class Options {
210210
features: Feature = Feature.MUTABLE_GLOBALS;
211211
/** If true, disallows unsafe features in user code. */
212212
noUnsafe: bool = false;
213+
/** If true, enables pedantic diagnostics. */
214+
pedantic: bool = false;
213215

214216
/** Hinted optimize level. Not applied by the compiler itself. */
215217
optimizeLevelHint: i32 = 0;
@@ -236,6 +238,11 @@ export class Options {
236238
return this.target == Target.WASM64 ? NativeType.I64 : NativeType.I32;
237239
}
238240

241+
/** Gets if any optimizations will be performed. */
242+
get willOptimize(): bool {
243+
return this.optimizeLevelHint > 0 || this.shrinkLevelHint > 0;
244+
}
245+
239246
/** Tests if a specific feature is activated. */
240247
hasFeature(feature: Feature): bool {
241248
return (this.features & feature) != 0;
@@ -322,6 +329,8 @@ export class Compiler extends DiagnosticEmitter {
322329
skippedAutoreleases: Set<ExpressionRef> = new Set();
323330
/** Current inline functions stack. */
324331
inlineStack: Function[] = [];
332+
/** Lazily compiled library functions. */
333+
lazyLibraryFunctions: Set<Function> = new Set();
325334

326335
/** Compiles a {@link Program} to a {@link Module} using the specified options. */
327336
static compile(program: Program): Module {
@@ -387,7 +396,7 @@ export class Compiler extends DiagnosticEmitter {
387396
}
388397
}
389398

390-
// compile the start function if not empty or explicitly requested
399+
// compile the start function if not empty or if explicitly requested
391400
var startIsEmpty = !startFunctionBody.length;
392401
var explicitStart = options.explicitStart;
393402
if (!startIsEmpty || explicitStart) {
@@ -414,11 +423,39 @@ export class Compiler extends DiagnosticEmitter {
414423
else module.addFunctionExport(startFunctionInstance.internalName, ExportNames.start);
415424
}
416425

417-
// compile runtime features
418-
if (this.runtimeFeatures & RuntimeFeatures.visitGlobals) compileVisitGlobals(this);
419-
if (this.runtimeFeatures & RuntimeFeatures.visitMembers) compileVisitMembers(this);
426+
// check if the entire program is acyclic
427+
var cyclicClasses = program.findCyclicClasses();
428+
if (cyclicClasses.size) {
429+
if (options.pedantic) {
430+
for (let classInstance of cyclicClasses) {
431+
this.info(
432+
DiagnosticCode.Type_0_is_cyclic_Module_will_include_deferred_garbage_collection,
433+
classInstance.identifierNode.range, classInstance.internalName
434+
);
435+
}
436+
}
437+
} else {
438+
program.registerConstantInteger("__GC_ALL_ACYCLIC", Type.bool, i64_new(1, 0));
439+
}
440+
441+
// compile lazy library functions
442+
var lazyLibraryFunctions = this.lazyLibraryFunctions;
443+
do {
444+
let functionsToCompile = new Array<Function>();
445+
for (let instance of lazyLibraryFunctions) {
446+
functionsToCompile.push(instance);
447+
}
448+
lazyLibraryFunctions.clear();
449+
for (let i = 0, k = functionsToCompile.length; i < k; ++i) {
450+
this.compileFunction(unchecked(functionsToCompile[i]), true);
451+
}
452+
} while (lazyLibraryFunctions.size);
453+
454+
// finalize runtime features
420455
module.removeGlobal(BuiltinNames.rtti_base);
421456
if (this.runtimeFeatures & RuntimeFeatures.RTTI) compileRTTI(this);
457+
if (this.runtimeFeatures & RuntimeFeatures.visitGlobals) compileVisitGlobals(this);
458+
if (this.runtimeFeatures & RuntimeFeatures.visitMembers) compileVisitMembers(this);
422459

423460
// update the heap base pointer
424461
var memoryOffset = this.memoryOffset;
@@ -464,8 +501,24 @@ export class Compiler extends DiagnosticEmitter {
464501
module.setFunctionTable(1 + functionTable.length, Module.UNLIMITED_TABLE, functionTable, module.i32(1));
465502

466503
// import and/or export table if requested (default table is named '0' by Binaryen)
467-
if (options.importTable) module.addTableImport("0", "env", "table");
468-
if (options.exportTable) module.addTableExport("0", ExportNames.table);
504+
if (options.importTable) {
505+
module.addTableImport("0", "env", "table");
506+
if (options.pedantic && options.willOptimize) {
507+
this.warning(
508+
DiagnosticCode.Importing_the_table_disables_some_indirect_call_optimizations,
509+
null
510+
);
511+
}
512+
}
513+
if (options.exportTable) {
514+
module.addTableExport("0", ExportNames.table);
515+
if (options.pedantic && options.willOptimize) {
516+
this.warning(
517+
DiagnosticCode.Exporting_the_table_disables_some_indirect_call_optimizations,
518+
null
519+
);
520+
}
521+
}
469522

470523
// set up module exports
471524
for (let file of this.program.filesByName.values()) {
@@ -1101,11 +1154,15 @@ export class Compiler extends DiagnosticEmitter {
11011154
forceStdAlternative: bool = false
11021155
): bool {
11031156
if (instance.is(CommonFlags.COMPILED)) return true;
1104-
if (instance.hasDecorator(DecoratorFlags.BUILTIN)) {
1105-
if (!forceStdAlternative) return true;
1157+
if (!forceStdAlternative) {
1158+
if (instance.hasDecorator(DecoratorFlags.BUILTIN)) return true;
1159+
if (instance.hasDecorator(DecoratorFlags.LAZY)) {
1160+
this.lazyLibraryFunctions.add(instance);
1161+
return true;
1162+
}
11061163
}
11071164

1108-
var previousType = this.currentType; // remember to retain it if compiling a function lazily
1165+
var previousType = this.currentType;
11091166
instance.set(CommonFlags.COMPILED);
11101167

11111168
var module = this.module;

Diff for: src/diagnosticMessages.generated.ts

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ export enum DiagnosticCode {
3737
_0_must_be_a_power_of_two = 223,
3838
_0_is_not_a_valid_operator = 224,
3939
Expression_cannot_be_represented_by_a_type = 225,
40+
Type_0_is_cyclic_Module_will_include_deferred_garbage_collection = 900,
41+
Importing_the_table_disables_some_indirect_call_optimizations = 901,
42+
Exporting_the_table_disables_some_indirect_call_optimizations = 902,
4043
Unterminated_string_literal = 1002,
4144
Identifier_expected = 1003,
4245
_0_expected = 1005,
@@ -181,6 +184,9 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
181184
case 223: return "'{0}' must be a power of two.";
182185
case 224: return "'{0}' is not a valid operator.";
183186
case 225: return "Expression cannot be represented by a type.";
187+
case 900: return "Type '{0}' is cyclic. Module will include deferred garbage collection.";
188+
case 901: return "Importing the table disables some indirect call optimizations.";
189+
case 902: return "Exporting the table disables some indirect call optimizations.";
184190
case 1002: return "Unterminated string literal.";
185191
case 1003: return "Identifier expected.";
186192
case 1005: return "'{0}' expected.";

Diff for: src/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
"'{0}' is not a valid operator.": 224,
3232
"Expression cannot be represented by a type.": 225,
3333

34+
"Type '{0}' is cyclic. Module will include deferred garbage collection.": 900,
35+
"Importing the table disables some indirect call optimizations.": 901,
36+
"Exporting the table disables some indirect call optimizations.": 902,
37+
3438
"Unterminated string literal.": 1002,
3539
"Identifier expected.": 1003,
3640
"'{0}' expected.": 1005,

0 commit comments

Comments
 (0)