diff --git a/ejs b/ejs index 459d800c..2756d058 100755 --- a/ejs +++ b/ejs @@ -17,6 +17,7 @@ temp_files = [] options = # our defaults: debug_level: 0 + frozen_global: false record_types: false output_filename: null combine_scripts: false @@ -95,6 +96,9 @@ args = "--record-types": flag: "record_types" help: "generates an executable which records types in a format later used for optimizations." + "--frozen-global": + flag: "frozen_global" + help: "compiler acts as if the global object is frozen after initialization, allowing for faster access." output_usage = -> console.warn 'Usage:'; diff --git a/lib/compiler.coffee b/lib/compiler.coffee index 080027ba..7fd801e1 100644 --- a/lib/compiler.coffee +++ b/lib/compiler.coffee @@ -278,6 +278,7 @@ class LLVMIRVisitor extends TreeVisitor @ejs_runtime = runtime.createInterface module, @abi @ejs_binops = runtime.createBinopsInterface module, @abi @ejs_atoms = runtime.createAtomsInterface module + @ejs_globals = runtime.createGlobalsInterface module @module_atoms = Object.create null @literalInitializationFunction = @module.getOrInsertFunction "_ejs_module_init_string_literals_#{@filename}", types.void, [] @@ -293,7 +294,7 @@ class LLVMIRVisitor extends TreeVisitor @doInsideBBlock entry_bb, => ir.createBr return_bb @doInsideBBlock return_bb, => - @createCall @ejs_runtime.log, [(consts.string ir, "done with literal initialization")], "" + #@createCall @ejs_runtime.log, [(consts.string ir, "done with literal initialization")], "" ir.createRetVoid() @literalInitializationBB = entry_bb @@ -328,7 +329,9 @@ class LLVMIRVisitor extends TreeVisitor ir.createStore consts.int64_lowhi(0xfff98000, if n then 0x00000001 else 0x000000000), alloca_as_int64 else ir.createStore consts.int64_lowhi(0xffffff83, if n then 0x00000001 else 0x00000000), alloca_as_int64 - ir.createLoad bool_alloca, "#{name}_load" + rv = ir.createLoad bool_alloca, "#{name}_load" + rv._ejs_returns_ejsval_bool = true + rv loadDoubleEjsValue: (n) -> c = llvm.ConstantFP.getDouble n @@ -369,8 +372,13 @@ class LLVMIRVisitor extends TreeVisitor @createCall @ejs_runtime.global_setprop, [c, value], "globalpropstore_#{pname}" loadGlobal: (prop) -> - pname = @getAtom prop.name - @createCall @ejs_runtime.global_getprop, [pname], "globalloadprop_#{prop.name}" + gname = prop.name + + if @options.frozen_global and hasOwn.call @ejs_globals, gname + return ir.createLoad @ejs_globals[prop.name], "load-#{gname}" + + pname = @getAtom gname + @createCall @ejs_runtime.global_getprop, [pname], "globalloadprop_#{gname}" visitWithScope: (scope, children) -> @scope_stack.push scope @@ -594,7 +602,7 @@ class LLVMIRVisitor extends TreeVisitor generateCondBr: (exp, then_bb, else_bb) -> exp_value = @visit exp if exp_value._ejs_returns_ejsval_bool - cmp = @createEjsvalCmpEq exp_value, (@loadBoolEjsValue false), "cmpresult" + cmp = @createEjsvalCmpEq exp_value, @loadBoolEjsValue(false), "cmpresult" else cond_truthy = @createCall @ejs_runtime.truthy, [exp_value], "cond_truthy" cmp = ir.createICmpEq cond_truthy, consts.false(), "cmpresult" @@ -1609,10 +1617,12 @@ class LLVMIRVisitor extends TreeVisitor new_local_val handleGetGlobal: (exp, opencode) -> - pname = @getAtom exp.arguments[0].name - @createCall @ejs_runtime.global_getprop, [pname], "globalloadprop_#{exp.arguments[0].name}" + @loadGlobal exp.arguments[0] handleSetGlobal: (exp, opencode) -> + if @options.frozen_global + throw new SyntaxError "cannot set global property '#{exp.arguments[0].name}' when using --frozen-global" + pname = @getAtom exp.arguments[0].name value = @visit exp.arguments[1] diff --git a/lib/runtime.coffee b/lib/runtime.coffee index a92b0587..18b4c1ea 100644 --- a/lib/runtime.coffee +++ b/lib/runtime.coffee @@ -124,4 +124,27 @@ exports.createAtomsInterface = (module) -> "Object": { get: -> module.getOrInsertGlobal "_ejs_atom_Object", types.EjsValue } "Array": { get: -> module.getOrInsertGlobal "_ejs_atom_Array", types.EjsValue } } - \ No newline at end of file + +exports.createGlobalsInterface = (module) -> + return Object.create null, { + "Object": { get: -> module.getOrInsertGlobal "_ejs_Object", types.EjsValue } + "Boolean": { get: -> module.getOrInsertGlobal "_ejs_Boolean", types.EjsValue } + "String": { get: -> module.getOrInsertGlobal "_ejs_String", types.EjsValue } + "Number": { get: -> module.getOrInsertGlobal "_ejs_Number", types.EjsValue } + "Array": { get: -> module.getOrInsertGlobal "_ejs_Array", types.EjsValue } + "Date": { get: -> module.getOrInsertGlobal "_ejs_Date", types.EjsValue } + "Error": { get: -> module.getOrInsertGlobal "_ejs_Error", types.EjsValue } + "Function": { get: -> module.getOrInsertGlobal "_ejs_Function", types.EjsValue } + "JSON": { get: -> module.getOrInsertGlobal "_ejs_JSON", types.EjsValue } + "Math": { get: -> module.getOrInsertGlobal "_ejs_Math", types.EjsValue } + "console": { get: -> module.getOrInsertGlobal "_ejs_console", types.EjsValue } + "require": { get: -> module.getOrInsertGlobal "_ejs_require", types.EjsValue } + "ArrayBuffer": { get: -> module.getOrInsertGlobal "_ejs_ArrayBuffer", types.EjsValue } + "Int8Array": { get: -> module.getOrInsertGlobal "_ejs_Int8Array", types.EjsValue } + "Uint16Array": { get: -> module.getOrInsertGlobal "_ejs_Uint16Array", types.EjsValue } + "Int32Array": { get: -> module.getOrInsertGlobal "_ejs_Int32Array", types.EjsValue } + "Float32Array": { get: -> module.getOrInsertGlobal "_ejs_Float32Array", types.EjsValue } + # kind of a hack, but since we don't define these... + "window": { get: -> module.getOrInsertGlobal "_ejs_undefined", types.EjsValue } + "document": { get: -> module.getOrInsertGlobal "_ejs_undefined", types.EjsValue } + } diff --git a/runtime/ejs-console.c b/runtime/ejs-console.c index 4af44d93..b3cef869 100644 --- a/runtime/ejs-console.c +++ b/runtime/ejs-console.c @@ -103,11 +103,12 @@ _ejs_console_warn (ejsval env, ejsval _this, uint32_t argc, ejsval *args) return output (stderr, argc, args); } +ejsval _ejs_console EJSVAL_ALIGNMENT; void _ejs_console_init(ejsval global) { - ejsval _ejs_console = _ejs_object_new (_ejs_null, &_ejs_object_specops); + _ejs_console = _ejs_object_new (_ejs_null, &_ejs_object_specops); _ejs_object_setprop (global, _ejs_atom_console, _ejs_console); #define OBJ_METHOD(x) EJS_INSTALL_ATOM_FUNCTION(_ejs_console, x, _ejs_console_##x) diff --git a/runtime/ejs-console.h b/runtime/ejs-console.h index 080059fe..a472bda2 100644 --- a/runtime/ejs-console.h +++ b/runtime/ejs-console.h @@ -10,6 +10,8 @@ EJS_BEGIN_DECLS +ejsval _ejs_console; + void _ejs_console_init(ejsval global); EJS_END_DECLS diff --git a/runtime/ejs-json.h b/runtime/ejs-json.h index 5bcac172..f7b336d6 100644 --- a/runtime/ejs-json.h +++ b/runtime/ejs-json.h @@ -9,7 +9,7 @@ EJS_BEGIN_DECLS -extern ejsval _ejs_Json; +extern ejsval _ejs_JSON; void _ejs_json_init(ejsval global);