Skip to content

Commit ab71d93

Browse files
authored
Add a low memory limit hint (#1090)
1 parent 58e7fd3 commit ab71d93

File tree

69 files changed

+515
-321
lines changed

Some content is hidden

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

69 files changed

+515
-321
lines changed

cli/asc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ exports.main = function main(argv, options, callback) {
247247
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
248248
assemblyscript.setNoUnsafe(compilerOptions, args.noUnsafe);
249249
assemblyscript.setPedantic(compilerOptions, args.pedantic);
250+
assemblyscript.setLowMemoryLimit(compilerOptions, args.lowMemoryLimit >>> 0);
250251

251252
// Add or override aliases if specified
252253
if (args.use) {

cli/asc.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@
192192
"type": "S",
193193
"alias": "u"
194194
},
195+
"lowMemoryLimit": {
196+
"category": "Features",
197+
"description": "Enforces very low (<64k) memory constraints.",
198+
"default": 0,
199+
"type": "i"
200+
},
195201

196202
"memoryBase": {
197203
"category": "Linking",

src/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ export namespace CommonNames {
154154
export const ASC_TABLE_BASE = "ASC_TABLE_BASE";
155155
export const ASC_OPTIMIZE_LEVEL = "ASC_OPTIMIZE_LEVEL";
156156
export const ASC_SHRINK_LEVEL = "ASC_SHRINK_LEVEL";
157+
export const ASC_LOW_MEMORY_LIMIT = "ASC_LOW_MEMORY_LIMIT";
157158
export const ASC_WASI = "ASC_WASI";
158159
export const ASC_FEATURE_SIGN_EXTENSION = "ASC_FEATURE_SIGN_EXTENSION";
159160
export const ASC_FEATURE_MUTABLE_GLOBALS = "ASC_FEATURE_MUTABLE_GLOBALS";

src/compiler.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ export class Options {
219219
noUnsafe: bool = false;
220220
/** If true, enables pedantic diagnostics. */
221221
pedantic: bool = false;
222+
/** Indicates a very low (<64k) memory limit. */
223+
lowMemoryLimit: i32 = 0;
222224

223225
/** Hinted optimize level. Not applied by the compiler itself. */
224226
optimizeLevelHint: i32 = 0;
@@ -361,7 +363,7 @@ export class Compiler extends DiagnosticEmitter {
361363
this.memoryOffset = i64_new(options.memoryBase);
362364
module.setLowMemoryUnused(false);
363365
} else {
364-
if (options.optimizeLevelHint >= 2) {
366+
if (options.optimizeLevelHint >= 2 && !options.lowMemoryLimit) {
365367
this.memoryOffset = i64_new(1024);
366368
module.setLowMemoryUnused(true);
367369
} else {
@@ -502,6 +504,16 @@ export class Compiler extends DiagnosticEmitter {
502504
// update the heap base pointer
503505
var memoryOffset = this.memoryOffset;
504506
memoryOffset = i64_align(memoryOffset, options.usizeType.byteSize);
507+
var lowMemoryLimit32 = this.options.lowMemoryLimit;
508+
if (lowMemoryLimit32) {
509+
let lowMemoryLimit = i64_new(lowMemoryLimit32 & ~15);
510+
if (i64_gt(memoryOffset, lowMemoryLimit)) {
511+
this.error(
512+
DiagnosticCode.Low_memory_limit_exceeded_by_static_data_0_1,
513+
null, i64_to_string(memoryOffset), i64_to_string(lowMemoryLimit)
514+
);
515+
}
516+
}
505517
this.memoryOffset = memoryOffset;
506518
module.removeGlobal(BuiltinNames.heap_base);
507519
if (this.runtimeFeatures & RuntimeFeatures.HEAP) {
@@ -526,7 +538,7 @@ export class Compiler extends DiagnosticEmitter {
526538
var isSharedMemory = options.hasFeature(Feature.THREADS) && options.sharedMemory > 0;
527539
module.setMemory(
528540
this.options.memoryBase /* is specified */ || this.memorySegments.length
529-
? i64_low(i64_shr_u(i64_align(memoryOffset, 0x10000), i64_new(16, 0)))
541+
? i64_low(i64_shr_u(i64_align(memoryOffset, 0x10000), i64_new(16)))
530542
: 0,
531543
isSharedMemory ? options.sharedMemory : Module.UNLIMITED_MEMORY,
532544
this.memorySegments,

src/diagnosticMessages.generated.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export enum DiagnosticCode {
1212
User_defined_0 = 102,
1313
Feature_0_is_not_enabled = 103,
1414
Function_0_is_possibly_called_virtually_which_is_not_yet_supported = 104,
15+
Low_memory_limit_exceeded_by_static_data_0_1 = 105,
1516
Conversion_from_type_0_to_1_requires_an_explicit_cast = 200,
1617
Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201,
1718
Type_0_cannot_be_changed_to_type_1 = 202,
@@ -165,6 +166,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
165166
case 102: return "User-defined: {0}";
166167
case 103: return "Feature '{0}' is not enabled.";
167168
case 104: return "Function '{0}' is possibly called virtually, which is not yet supported.";
169+
case 105: return "Low memory limit exceeded by static data: {0} > {1}";
168170
case 200: return "Conversion from type '{0}' to '{1}' requires an explicit cast.";
169171
case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.";
170172
case 202: return "Type '{0}' cannot be changed to type '{1}'.";

src/diagnosticMessages.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"User-defined: {0}": 102,
55
"Feature '{0}' is not enabled.": 103,
66
"Function '{0}' is possibly called virtually, which is not yet supported.": 104,
7+
"Low memory limit exceeded by static data: {0} > {1}": 105,
78

89
"Conversion from type '{0}' to '{1}' requires an explicit cast.": 200,
910
"Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201,

src/glue/js/i64.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ declare function i64_not(value: i64): i64;
2929

3030
declare function i64_eq(left: i64, right: i64): bool;
3131
declare function i64_ne(left: i64, right: i64): bool;
32+
declare function i64_gt(left: i64, right: i64): bool;
3233

3334
declare function i64_align(value: i64, alignment: i32): i64;
3435

src/glue/js/i64.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ global.i64_ne = function(left, right) {
8585
return left.ne(right);
8686
};
8787

88+
global.i64_gt = function(left, right) {
89+
return left.gt(right);
90+
};
91+
8892
global.i64_align = function(value, alignment) {
8993
assert(alignment && (alignment & (alignment - 1)) == 0);
9094
var mask = Long.fromInt(alignment - 1);

src/glue/wasm/i64.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ function i64_ne(left: i64, right: i64): bool {
125125
return left != right;
126126
}
127127

128+
// @ts-ignore: decorator
129+
@global
130+
function i64_gt(left: i64, right: i64): bool {
131+
return left > right;
132+
}
133+
128134
// @ts-ignore: decorator
129135
@global
130136
function i64_align(value: i64, alignment: i64): i64 {

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ export function setNoUnsafe(options: Options, noUnsafe: bool): void {
109109
options.noUnsafe = noUnsafe;
110110
}
111111

112+
/** Sets the `lowMemoryLimit` option. */
113+
export function setLowMemoryLimit(options: Options, lowMemoryLimit: i32): void {
114+
options.lowMemoryLimit = lowMemoryLimit;
115+
}
116+
112117
/** Sign extension operations. */
113118
export const FEATURE_SIGN_EXTENSION = Feature.SIGN_EXTENSION;
114119
/** Mutable global imports and exports. */

0 commit comments

Comments
 (0)