コード例 #1
0
ファイル: entity-test.js プロジェクト: js-js/heap.js
      it('should invoke assembly code via wrapper', function() {
        var wrapperCode = jit.compile(function() {
          this.Proc(function() {
            assert.equal(this.arch, 'x64');

            this.spill([ 'rbx', 'r12', 'r13', 'r14', 'r15' ], function() {
              // Shift args
              this.mov('rax', 'rdi');
              this.mov('rdi', 'rsi');
              this.mov('rsi', 'rdx');
              this.mov('rdx', 'rcx');
              this.mov('rcx', 'r8');

              this.call('rax');
            });
            this.Return();
          });
        })._buffer;

        // NOTE: Old wrapper code
        function wrapper(fn, state, self, args) {
          var argv = args.map(function(arg) {
            return arg.deref();
          });
          argv.unshift(state.deref());
          argv.unshift(self.deref());
          argv.unshift(fn.code().code());
          return heap.binding.call(wrapperCode, argv);
        }
        var h = heap.create({ callWrapper: wrapper });

        var code = jit.generate(function() {
          this.Proc(function() {
            assert.equal(this.arch, 'x64');
            this.mov('rax', 'rcx');
            this.Return();
          });
        });
        var c = h.allocCode(code.buffer, []);
        code.resolve(c.deref());

        var fn = h.allocFunction(c);
        var r = fn.call(h.allocObject(32), [
          h.allocString('hello'),
          h.allocString('ohai')
        ]);
        assert.equal(r.cast().value(), 'ohai');
      });
コード例 #2
0
ファイル: entity-test.js プロジェクト: bmeck/heap.js
      it('should invoke assembly code via wrapper', function() {
        var wrapper = jit.compile(function() {
          this.Proc(function() {
            assert.equal(this.arch, 'x64');

            this.spill([ 'rbx', 'r12', 'r13', 'r14', 'r15' ], function() {
              // Shift args
              this.mov('rax', 'rdi');
              this.mov('rdi', 'rsi');
              this.mov('rsi', 'rdx');
              this.mov('rdx', 'rcx');
              this.mov('rcx', 'r8');

              this.call('rax');
            });
            this.Return();
          });
        })._buffer;
        var h = heap.create({ callWrapper: wrapper });

        var code = jit.generate(function() {
          this.Proc(function() {
            assert.equal(this.arch, 'x64');
            this.mov('rax', 'rcx');
            this.Return();
          });
        });
        var c = h.allocCode(code.buffer, []);
        code.resolve(c.deref());

        var fn = h.allocFunction(c);
        var r = fn.call(h.allocObject(32), [
          h.allocString('hello'),
          h.allocString('ohai')
        ]);
        assert.equal(r.cast().toString(), 'ohai');
      });
コード例 #3
0
ファイル: compiler.js プロジェクト: inikulin/js.js
function Context(compiler, options) {
  this.compiler = compiler;
  this.heap = this.compiler.heap;

  this.block = null;

  this.masm = jit.create(util._extend({
    stubs: this.compiler.platform.stubs,
    helpers: this.compiler.platform.helpers
  }, options || {}));
  this.masm.ctx = this;

  this.references = null;
  this.offsets = [];
  this.blocks = {};
}
コード例 #4
0
ファイル: entity-test.js プロジェクト: bmeck/heap.js
      it('should invoke assembly code', function() {
        var code = jit.generate(function() {
          this.Proc(function() {
            assert.equal(this.arch, 'x64');
            this.mov('rax', 'rcx');
            this.Return();
          });
        });
        var c = h.allocCode(code.buffer, []);
        code.resolve(c.deref());

        var fn = h.allocFunction(c);
        var r = fn.call(null, [
          h.allocString('hello'),
          h.allocString('ohai')
        ]);
        assert.equal(r.cast().toString(), 'ohai');
      });
コード例 #5
0
ファイル: index.js プロジェクト: a8m/js.js
function Base(runtime) {
  this.runtime = runtime;
  this.ctx = null;

  this._baseState = new BaseState();

  // NOTE: will be set by runtime
  this.heap = null;
  this.compiler = null;

  this.helpers = util._extend({}, Base.helpers);
  this.helpers.platform = this;

  this.ptrSize = 0;

  this.Stub = stub.Stub;
  this.IC = ic.IC;

  // Get helpers, args, ret
  this.init();

  this.registers = null;
  this.instructions = Base.instructions.get.call(this);
  this.instructionMethods = null;

  var self = this;
  this.stubs = jit.stubs({
    helpers: this.helpers,
    compile: function(body, options) {
      return self.ctx.compiler.compileStubs(body, options);
    }
  });

  this.cfgStubs = {};

  this.initStubs();
}
コード例 #6
0
ファイル: index.js プロジェクト: a8m/js.js
X64.prototype.initCallWrapper = function initCallWrapper() {
  var self = this;
  var proc = jit.compile(function() {
    this.Proc(function() {
      // Callee-save
      this.spill([ 'rbx', 'r12', 'r13', 'r14', 'r15' ], function() {
        // rdi = code
        // rsi = state
        // rdx = buf.length
        // rcx = buf

        // Copy frame from buffer to stack
        var loop = this.label();
        this.shr('rdx', heap.tagShift);
        this.lea('rcx', [ 'rcx', -heap.tagPointer ]);
        this.lea('rdx', [ 'rcx', 'rdx', -heap.ptrSize]);

        // NOTE: assumes that the buffer is never empty
        this.bind(loop);
        this.push([ 'rdx' ]);
        this.sub('rdx', heap.ptrSize);
        this.cmp('rdx', 'rcx');
        this.j('ge', loop);

        // Untag code
        this.lea('rax', [ 'rdi', -heap.tagPointer ]);

        // Load state (note: 'rdi' === self.state, so previous line should
        // be previous)
        this.mov(self.state, 'rsi');

        // Untag code pointer
        this.alignedCall('rax');
      });
      this.Return();
    });
  }, { helpers: X64.helpers })._buffer;

  this.callWrapper = function callWrapper(fn, ctx, self, argv) {
    // Aligned frame length
    var len = heap.ptrSize * (3 + argv.length);
    if (len % (2 * heap.ptrSize) !== 0)
      len += heap.ptrSize;
    var frame = new Buffer(len);
    var off = 0;

    // This
    heap.binding.writeTagged(frame, self.deref(), off);
    off += heap.ptrSize;

    // Self
    heap.binding.writeTagged(frame, fn.deref(), off);
    off += heap.ptrSize;

    // Argc
    heap.binding.writeTagged(frame, argv.length, off);
    off += heap.ptrSize;

    // Copy all args
    for (var i = 0; i < argv.length; i++, off += heap.ptrSize)
      heap.binding.writeTagged(frame, argv[i].deref(), off);

    // Fill rest with zeroes
    for (; off !== frame.length; off += heap.ptrSize)
      heap.binding.writeTagged(frame, 0, off);

    var code = fn.code().code();
    return heap.binding.call(proc, [ code, ctx.deref(), frame.length, frame ]);
  };
};
コード例 #7
0
ファイル: main.js プロジェクト: js-js/jit.js
#!/usr/bin/env node
var jit = require('jit.js'),
    esprima = require('esprima'),
    assert = require('assert');

var ast = esprima.parse(process.argv[2]);

// Compile
var fn = jit.compile(function() {
  // This will generate default entry boilerplate
  this.Proc(function() {
    visit.call(this, ast);

    // The result should be in 'rax' at this point
    //
    // This will generate default exit boilerplate
    this.Return();
  });
});

// Execute
console.log(fn());

function visit(ast) {
  if (ast.type === 'Program')
    visitProgram.call(this, ast);
  else if (ast.type === 'Literal')
    visitLiteral.call(this, ast);
  else if (ast.type === 'UnaryExpression')
    visitUnary.call(this, ast);
  else if (ast.type === 'BinaryExpression')
コード例 #8
0
ファイル: base.js プロジェクト: inikulin/js.js
function Base(runtime) {
  this.runtime = runtime;
  this.ctx = null;

  this._baseState = new BaseState();

  // NOTE: will be set by runtime
  this.heap = null;

  this.helpers = util._extend({}, Base.helpers);
  this.helpers.platform = this;

  this.ptrSize = 0;

  // Get helpers, args, ret
  this.init();

  var out = { type: 'register', id: this.ret };
  var reg = { type: 'register' };

  this.registers = null;
  this.instructions = {
    literal: { inputs: [ { type: 'js' } ], output: reg },
    binary: {
      inputs: [ { type: 'js' }, reg, reg ],
      output: out,
      shallow: true
    },
    ret: { inputs: [ out ], output: null },
    global: {
      inputs: [],
      output: reg
    },
    'this': {
      inputs: [],
      output: reg
    },
    self: {
      inputs: [],
      output: reg
    },
    allocHashMap: {
      inputs: [ { type: 'js' } ],
      output: out
    },
    allocObject: {
      inputs: [ reg ],
      output: out
    },
    loadProperty: {
      inputs: [ reg, reg ],
      output: out,
      shallow: true
    },
    storeProperty: {
      inputs: [ reg, reg, reg ],
      output: out,
      shallow: true
    },
    toBoolean: {
      inputs: [ reg ],
      output: out,
      shallow: true
    },
    branch: {
      inputs: [ reg ],
      output: null
    },
    nop: {
      inputs: [ { type: 'any' } ],
      output: [ reg ]
    },
    loadArg: {
      inputs: [ { type: 'js' } ],
      output: reg
    },
    pushArg: {
      inputs: [ reg ],
      output: null
    },
    alignStack: {
      inputs: [ { type: 'js' } ],
      output: null
    },
    fn: {
      inputs: [ { type: 'js' } ],
      output: out
    },
    checkMap: {
      inputs: [ reg, { type: 'js' } ],
      output: null,
      shallow: true
    },
    call: {
      inputs: [ reg, reg, { type: 'js' } ],
      output: out,
      call: true,
      shallow: true
    }
  };

  var self = this;
  this.stubs = jit.stubs({
    helpers: this.helpers,
    compile: function(body, options) {
      return self.ctx.compiler.compileStubs(body, options);
    }
  });

  this.initStubs();
}
コード例 #9
0
ファイル: entity-test.js プロジェクト: js-js/heap.js
    describe('placing in object', function() {
      var acc = new Buffer(heap.ptrSize);
      var getCode = jit.generate(function() {
        this.Proc(function() {
          assert.equal(this.arch, 'x64');
          this.mov('rax', acc.ref());
          this.add([ 'rax' ], 1 << heap.tagShift);
          this.mov('rax', [ 'rax' ]);
          this.Return();
        });
      });
      var setCode = jit.generate(function() {
        this.Proc(function() {
          assert.equal(this.arch, 'x64');
          this.mov('rax', acc.ref());
          this.mov([ 'rax' ], 'rdx');
          this.Return();
        });
      });

      it('should invoke getter', function() {
        acc.fill(0);

        var getter = h.allocFunction(h.allocCode(getCode.buffer));
        var pair = h.allocAccessPair({
          getter: getter
        });

        var o = h.allocObject();
        var key = h.allocString('key');
        o.set(key, pair);

        assert.equal(o.get(key).cast().value(), 1);
        assert.equal(o.get(key).cast().value(), 2);
      });

      it('should invoke setter', function() {
        acc.fill(0);

        var getter = h.allocFunction(h.allocCode(getCode.buffer));
        var setter = h.allocFunction(h.allocCode(setCode.buffer));
        var pair = h.allocAccessPair({
          getter: getter,
          setter: setter
        });

        var o = h.allocObject();
        var key = h.allocString('key');
        o.set(key, pair);

        assert.equal(o.get(key).cast().value(), 1);
        assert.equal(o.get(key).cast().value(), 2);
        o.set(key, h.smi(42));
        assert.equal(o.get(key).cast().value(), 43);
        assert.equal(o.get(key).cast().value(), 44);
      });

      it('should work with no getter/setter', function() {
        var pair = h.allocAccessPair();

        var o = h.allocObject();
        var key = h.allocString('key');
        o.set(key, pair);

        assert(o.get(key).isUndef());
        o.set(key, h.smi(42));
        assert(o.get(key).isUndef());
      });

      it('should be enumerable by default', function() {
        var pair = h.allocAccessPair();

        var o = h.allocObject();
        var key = h.allocString('key');
        o.set(key, pair);

        assert.deepEqual(o.toJSON(), { key: undefined });
      });

      it('should support custom attributes', function() {
        var pair = h.allocAccessPair({
          enumerable: false
        });

        var o = h.allocObject();
        var key = h.allocString('key');
        o.set(key, pair);

        assert.deepEqual(o.toJSON(), {});
      });
    });