• Home
  • Raw
  • Download

Lines Matching full:to

26 Here comes the bytecode. Simply said, it is an attempt to build an abstract CPU on top of real
28 special program called _interpreter_. The goal of the interpreter is to read our unified _virtual_
30 making interpretation slower than _native code execution_. In return, we get the ability to
38 to distinguish between an abstract system and the hardware.
45 One very important question is how an operation refers to its operands.
52 push_arg1 ; copy the first argument to the top of the stack
53 push_arg2 ; copy the second argument to the top of stack
74 require up to 4 bytes to encode.
76 At the same time, to execute a stack-based addition we need to run 3 instructions compared to
77 just a single register-based instruction. Since the interpreter has an extra work to do to read
78 each bytecode instruction, execute it and move to the next one, running more instruction results in
81 According to our experiment, uncompressed register-based bytecode can be reduced by ~26%
89 However, to address the issue of compactness, two main tweaks are used:
92 * Variable size of instructions with frequent instructions are encoded to be smaller.
94 According to our research, these tweaks will allow to reduce the size of uncompressed bytecode by
95 ~20% compared to pure register-based bytecode.
110 With this approach, we are no longer required to encode destination register, it is "hardcoded" to
112 some "stack-based'ness" into an otherwise register-based instruction set in attempt to make the
115 In an ideal case, accumulator register may safe us ~25% of size. But it needs to be used carefully:
117 * Sometimes you might want to write directly into virtual register. e.g. for register moves (that
120 * You don't need to pass object reference in accumulator in the object call. Usually objects live
121 longer than accumulator value (otherwise calls will be accompanied with moves from and to
125 To address the risk of producing inefficient bytecode with redundant moves from and to
128 Finally, using accumulator allows getting rid of the instructions for writing the result to the reg…
133 Let's take a closer look at `adda arg1, arg2`. Assume that arguments map to virtual registers on
148 It easy to see that to address virtual registers 4 and 5 we need just 3 bits which allows to encode
157 to the stack-based approach. Of course, if virtual registers have large numbers that do no fit
158 into 4 bits, we have to use a wider encoding:
165 How to make sure that we benefit from the shorter encoding most of the time? An observation shows
168 function arguments to virtual registers with larger numbers reserving smaller ones for local
178 (which is rare) and which is supposed to have only acc-reg form. Another good candidates for
184 Another important question is how bytecode is supposed to handle various data types. Back to our
187 One option is to make the operation _statically typed_, i.e. specify explicitly that it works only
188 with say 64-bit integers. In this case, if we want to add two double-precision floating point
191 Another option is to make the operation _dynamically typed_, i.e. specify that `adda ...` handles
200 is true only if the platform is **not** supposed to support multiple languages.
202 Python? In JavaScript, it evaluates to the string `"42"`, while Python forbids adding a string to
203 a number without an explicit type cast. This means that if we would like to run these two languages
204 on the same platform with the same bytecode, we would have to handle both JavaScript-style addition
205 and Python-style addition within a single instruction, which would eventually lead us to an
208 Thus, as we are required to support multiple languages (both statically and dynamically typed),
211 There may be a concern: Does a statically typed bytecode forbid us to support a dynamically typed
212 language? No, it does not. In practice, it is always possible to compile a dynamically typed
213 language to some statically typed instruction set: after all, all native hardware instructions
223 bytecode verifiers take the responsibility to control this invariant.