⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asm.js

📁 一个类似windows
💻 JS
📖 第 1 页 / 共 4 页
字号:
      stream.write ("; -*- asm -*-\n");

      /* Set the prev properties. */
      var prev = null;
      for (i = JSC$asm_head; i != null; prev = i, i = i.next)
	i.prev = prev;

      /*
       * Fix the label line numbers to be the same that the next
       * assembler operand has.
       */
      last_ln = 0;
      for (i = JSC$asm_tail; i != null; i = i.prev)
	{
	  if (i.type == JSC$ASM_LABEL)
	    i.linenum = last_ln;
	  else if (typeof i.linenum != "undefined")
	    last_ln = i.linenum;
	}
    }

  last_ln = 0;
  for (i = JSC$asm_head; i != null; i = i.next)
    {
      if (typeof i.linenum == "undefined")
	{
	  if (annotate)
	    stream.write ("; undefined linenum\n");
	}
      else
	while (annotate && i.linenum > last_ln)
	  {
	    var line = src_stream.readln ();
	    stream.write ("; " + line + "\n");
	    last_ln++;
	  }

      i.print (stream);
    }
}


function JSC$asm_is_load_op (op)
{
  return (op.type == JSC$OP_LOAD_GLOBAL
	  || op.type == JSC$OP_LOAD_ARG
	  || op.type == JSC$OP_LOAD_LOCAL);
}


function JSC$asm_is_store_op (op)
{
  return (op.type == JSC$OP_STORE_GLOBAL
	  || op.type == JSC$OP_STORE_ARG
	  || op.type == JSC$OP_STORE_LOCAL);
}


function JSC$asm_is_local_jump (op)
{
  return (op.type == JSC$OP_JMP
	  || op.type == JSC$OP_IFFALSE
	  || op.type == JSC$OP_IFTRUE
	  || op.type == JSC$OP_IFFALSE_B
	  || op.type == JSC$OP_IFTRUE_B
	  || op.type == JSC$OP_TRY_PUSH);
}


function JSC$asm_is_const_op (op)
{
  return (JSC$OP_CONST <= op.type && op.type <= JSC$OP_CONST_I3);
}


function JSC$asm_lookup_next_op (item)
{
  while (item != null &&
	 (item.type == JSC$ASM_LABEL || item.type == JSC$ASM_SYMBOL))
    item = item.next;

  return item;
}


function JSC$asm_optimize (flags)
{
  var item;

  /* Simple peephole optimization. */
  if ((flags & JSC$FLAG_OPTIMIZE_PEEPHOLE) != 0)
    {
      if (JSC$verbose)
	JSC$message ("jsc: optimize: peephole");

      for (item = JSC$asm_head; item != null; item = item.next)
	{
	  /*
	   * Optimization for dup ... pop cases where pop removes the
	   * item duplicated by dup.
	   */
	  if (item.next != null && item.next.type == JSC$OP_DUP)
	    {
	      var balance = 2;
	      var found = false;
	      var i1;

	      for (i1 = item.next.next;
		   i1 != null && i1.next != null;
		   i1 = i1.next)
		{
		  var i2 = i1.next;

		  /*
		   * The lookup ends on branches, and on dup, throw,
		   * and try_pop operands.  We optimize on a basic
		   * block and we match the closest dup-pop pairs.
		   */
		  if (JSC$asm_is_local_jump (i1)
		      || i1.type == JSC$OP_JSR
		      || i1.type == JSC$OP_NEW
		      || i1.type == JSC$OP_CALL_METHOD
		      || i1.type == JSC$OP_RETURN
		      || i1.type == JSC$ASM_SYMBOL
		      || i1.type == JSC$ASM_LABEL
		      || i1.type == JSC$OP_DUP
		      || i1.type == JSC$OP_TRY_POP
		      || i1.type == JSC$OP_THROW)
		    break;

		  if (i1.stack_delta)
		    {
		      balance += i1.stack_delta;
		      if (balance <= 0)
			/* Going to negative.  Stop here. */
			break;
		    }

		  if (i2.type == JSC$OP_POP && balance == 1)
		    {
		      /* Found a matching pop. */
		      found = true;
		      i1.next = i2.next;
		      break;
		    }
		}

	      if (found)
		{
		  /* The dup can be removed. */
		  item.next = item.next.next;
		}
	    }

	  /* Two instruction optimization (starting from item.next). */
	  if (item.next != null && item.next.next != null)
	    {
	      var i1 = item.next;
	      var i2 = i1.next;

	      if (i1.type == JSC$OP_APOP
		  && i2.type == JSC$OP_POP)
		{
		  /*
		   * i1:	apop n
		   * i2:	pop		->	pop_n n + 1
		   */
		  var i = new JSC$ASM_pop_n (i1.linenum, i1.value + 1);
		  item.next = i;
		  i.next = i2.next;
		}
	    }
	  if (item.next != null && item.next.next != null)
	    {
	      var i1 = item.next;
	      var i2 = i1.next;

	      if (i1.type == JSC$OP_CONST_TRUE
		  && (i2.type == JSC$OP_IFFALSE
		      || i2.type == JSC$OP_IFFALSE_B))
		{
		  /*
		   * i1:	const_true
		   * i2:	iffalse{,_b}	.LX	=> ---
		   */
		  item.next = i2.next;
		}
	    }
	  if (item.next != null && item.next.next != null)
	    {
	      var i1 = item.next;
	      var i2 = i1.next;

	      if (i1.type == JSC$OP_CONST_FALSE
		  && (i2.type == JSC$OP_IFTRUE
		      || i2.type == JSC$OP_IFTRUE_B))
		{
		  /*
		   * i1:	const_false
		   * i2:	iftrue{,_b}	.LX	=> ---
		   */
		  item.next = i2.next;
		}
	    }
	  if (item.next != null && item.next.next != null)
	    {
	      var i1 = item.next;
	      var i2 = i1.next;

	      if ((i1.type == JSC$OP_CONST_FALSE
		   && (i2.type == JSC$OP_IFFALSE
		       || i2.type == JSC$OP_IFFALSE_B))
		  || (i1.type == JSC$OP_CONST_TRUE
		      && (i2.type == JSC$OP_IFTRUE
			  || i2.type == JSC$OP_IFTRUE_B)))
		{
		  /*
		   * i1:	const_false
		   * i2:	iffalse{,_b}	.LX	=> jmp .LX
		   *
		   * i1:	const_true
		   * i2:	iftrue{,_b}	.LX	=> jmp .LX
		   */
		  var i = new JSC$ASM_jmp (i1.linenum, i2.value);
		  item.next = i;
		  i.next = i2.next;
		}
	    }
	}
    }

  /* Jumps to jumps. */
  if ((flags & JSC$FLAG_OPTIMIZE_JUMPS) != 0)
    {
      if (JSC$verbose)
	JSC$message ("jsc: optimize: jumps to jumps");
      for (item = JSC$asm_head; item != null; item = item.next)
	if (JSC$asm_is_local_jump (item))
	  {
	    var i2;

	    /* Operand's value is a label */
	    i2 = JSC$asm_lookup_next_op (item.value);

	    if (i2 != null && i2.type == JSC$OP_JMP)
	      /* Ok, we can jump there directly. */
	      item.value = i2.value;
	  }
    }

  if ((flags & JSC$FLAG_OPTIMIZE_HEAVY) != 0)
    JSC$optimize_heavy ();

  /*
   * Optimizations for the size of the generated byte-code.  It isn't
   * probably worth of doing these optimization for interactive
   * scripts since these won't affect the speed of the execution.
   * However, these optimizations make the byte-code files smaller so
   * these are nice for batch-compiled files.
   */
  if ((flags & JSC$FLAG_OPTIMIZE_BC_SIZE) != 0)
    {
      var delta = true;

      while (delta)
	{
	  delta = false;

	  /* Remove un-referenced labels. */

	  if (JSC$verbose)
	    JSC$message ("jsc: optimize: removing un-referenced labels");

	  /* First, make all labels unreferenced. */
	  for (item = JSC$asm_head; item != null; item = item.next)
	    if (item.type == JSC$ASM_LABEL)
	      item.referenced = false;

	  /* Second, mark all referenced labels. */
	  for (item = JSC$asm_head; item != null; item = item.next)
	    if (JSC$asm_is_local_jump (item))
	      item.value.referenced = true;

	  /* Third, remove all un-referenced labels. */
	  for (item = JSC$asm_head; item != null; item = item.next)
	    while (item.next != null && item.next.type == JSC$ASM_LABEL
		   && !item.next.referenced
		   && item.next.next != null)
	      {
		delta = true;
		item.next = item.next.next;
	      }

	  /* Dead code elimination. */
	  if (JSC$verbose)
	    JSC$message ("jsc: optimize: dead code elimination");
	  for (item = JSC$asm_head; item != null; item = item.next)
	    if (item.type == JSC$OP_RETURN || item.type == JSC$OP_JMP)
	      while (item.next != null && item.next.type != JSC$ASM_SYMBOL
		     && item.next.type != JSC$ASM_LABEL)
		{
		  delta = true;
		  item.next = item.next.next;
		}


	  /* Simple peephole optimization. */
	  if (JSC$verbose)
	    JSC$message ("jsc: optimize: peephole");
	  for (item = JSC$asm_head; item != null; item = item.next)
	    {
	      /* Two instruction optimization (starting from item.next). */
	      if (item.next != null && item.next.next != null)
		{
		  var i1 = item.next;
		  var i2 = i1.next;

		  if (i1.type == JSC$OP_JMP
		      && i2.type == JSC$ASM_LABEL
		      && i1.value == i2)
		    {
		      /*
		       * i1:	jmp	.LX
		       * i2:	.LX		=> .LX
		       */
		      item.next = i2;
		      delta = true;
		    }
		}
	    }
	}
    }
}


function JSC$optimize_heavy ()
{
  if (JSC$verbose)
    JSC$message ("jsc: optimize: liveness analyzing");

  /* First, set the prev pointers and zero usage flags. */
  var item, prev = null;

  for (item = JSC$asm_head; item != null; prev = item, item = item.next)
    {
      item.prev = prev;
      item.live_args = 0;
      item.live_locals = 0;
      item.live_used = false;
    }

  /* For each function. */
  var ftail, fhead;
  for (ftail = JSC$asm_tail; ftail != null; ftail = fhead.prev)
    {
      var change = true;

      /* While there is change in the liveness. */
      while (change)
	{
	  change = false;

	  for (fhead = ftail;
	       fhead.type != JSC$ASM_SYMBOL;
	       fhead = fhead.prev)
	    {
	      var floc, farg;

	      if (fhead.next != null)
		{
		  floc = fhead.next.live_locals;
		  farg = fhead.next.live_args;
		}
	      else
		floc = farg = 0;

	      if (fhead.type == JSC$OP_LOAD_LOCAL && fhead.value < 32)
		floc |= (1 << fhead.value);

	      if (fhead.type == JSC$OP_STORE_LOCAL && fhead.value < 32)
		floc &= ~(1 << fhead.value);

	      if (fhead.type == JSC$OP_LOAD_ARG && fhead.value < 32)
		farg |= (1 << fhead.value);

	      if (fhead.type == JSC$OP_STORE_ARG && fhead.value < 32)
		farg &= ~(1 << fhead.value);

	      if (JSC$asm_is_local_jump (fhead))
		{
		  floc |= fhead.value.live_locals;
		  fhead.value.live_used = true;
		}

	      if (fhead.live_used && (fhead.live_locals != floc
				      || fhead.live_args != farg))
		change = true;

	      fhead.live_used = false;
	      fhead.live_locals = floc;
	      fhead.live_args = farg;
	    }
	}
    }

  /*
   * When we have the liveness analyzing performed, we can do some
   * fancy optimizations.
   */

  if (JSC$verbose)
    JSC$message ("jsc: optimize: peephole");

  for (item = JSC$asm_head; item != null; item = item.next)
    {
      /* Three instruction optimization. */
      if (item.next != null && item.next.next != null
	  && item.next.next.next != null)
	{
	  var i1 = item.next;
	  var i2 = i1.next;
	  var i3 = i2.next;

	  if (i1.type == JSC$OP_STORE_LOCAL
	      && i2.type == JSC$OP_LOAD_LOCAL
	      && i1.value == i2.value
	      && (i3.live_locals & (1 << i1.value)) == 0)
	    {
	      /*
	       * i1:	store_local 	n
	       * i2:	load_local	n
	       * i3:	nnn (n not live)	=> nnn
	       */

	      item.next = i3;
	    }
	}
    }
}


function JSC$asm_finalize ()
{
  var item;
  var offset = 0;

  for (item = JSC$asm_head; item != null; item = item.next)
    {
      item.offset = offset;
      offset += item.size;
    }
}


function JSC$ConstantReg ()
{
}

function JSC$asm_genconstant (val)
{
  if (JSC$asm_known_constants == null)
    JSC$asm_known_constants = new JSC$ConstantReg ();

  /* Lookup <val> from a list of known constants. */
  var id = JSC$asm_known_constants[val];
  if (typeof id == "number")
    return id;

  /* This is a new constant. */
  JSC$asm_constants.append (val);
  JSC$asm_known_constants[val] = JSC$asm_constcount;

  return JSC$asm_constcount++;
}

function JSC$asm_bytecode ()
{
  var item;
  var symtab = new String ("");
  var nsymtab_entries = 0;
  var code = new String ("");
  var debug = new String ("");
  var debug_last_linenum = 0;

  if (JSC$verbose)
    JSC$message ("jsc: generating byte-code");

  if (JSC$generate_debug_info)
    /* Source file name. */
    debug.append (String.pack ("CN", JSC$DEBUG_FILENAME, JSC$filename.length)
		  + JSC$filename);

  JSC$asm_constants = new String ("");

  for (item = JSC$asm_head; item != null; item = item.next)
    {
      if (item.type == JSC$ASM_SYMBOL)
	{
	  symtab.append (item.value + String.pack ("CN", 0, item.offset));
	  nsymtab_entries++;
	}
      else if (item.type == JSC$ASM_LABEL)
	;
      else
	{
	  /* Real assembler operands. */

	  if (JSC$generate_debug_info)
	    if (item.linenum != debug_last_linenum)
	      {
		debug.append (String.pack ("CNN", JSC$DEBUG_LINENUMBER,
					   item.offset + item.size,
					   item.linenum));
		debug_last_linenum = item.linenum;
	      }

	  if (item.size == 1)
	    /* We handle these. */
	    code.append (String.pack ("C", item.type));
	  else
	    {
	      /*
	       * All operands which take an argument, have a method to create
	       * the byte code entry for their argument.
	       */
	      code.append (String.pack ("C", item.type) + item.bytecode ());
	    }
	}
    }

  symtab = String.pack ("N", nsymtab_entries) + symtab;

  if (JSC$verbose)
    {
      var msg = ("jsc: code=" + code.length.toString ()
		 + ", constants=" + JSC$asm_constants.length.toString ()
		 + ", symtab=" + symtab.length.toString ());

      if (JSC$generate_debug_info)
	msg += ", debug=" + debug.length.toString ();

      msg += (", headers="
	      + (32 + (JSC$generate_debug_info ? 8 : 0)).toString ()
	      + ", total="
	      + (code.length + JSC$asm_constants.length + symtab.length
		 + debug.length + 32
		 + (JSC$generate_debug_info ? 8 : 0)).toString ());
      JSC$message (msg);
    }

  return (String.pack ("NN", JSC$BC_MAGIC,
		       3 + (JSC$generate_debug_info ? 1 : 0))
	  + String.pack ("NN", JSC$BC_SECT_CODE, code.length) + code

	  + String.pack ("NN", JSC$BC_SECT_CONSTANTS,
			 JSC$asm_constants.length)
	  + JSC$asm_constants

	  + String.pack ("NN", JSC$BC_SECT_SYMTAB, symtab.length) + symtab

	  + (JSC$generate_debug_info
	     ? String.pack ("NN", JSC$BC_SECT_DEBUG, debug.length) + debug
	     : ""));
}


/*
Local variables:
mode: c
End:
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -