I've got this problem I have been working on and found some interesting behavior. Basically, if I benchmark the same code multiple times in a row, the code execution gets significantly faster.
Here's the code:
http://codepen.io/kirkouimet/pen/xOXLPv?editors=0010
Here's a screenshot from Chrome:
Anybody know what's going on?
I'm checking performance with:
var benchmarkStartTimeInMilliseconds = performance.now();
...
var benchmarkEndTimeInMilliseconds = performance.now() - benchmarkStartTimeInMilliseconds;
Chrome's V8 optimizing compiler initially compiles your code without optimizations. If a certain part of your code is executed very often (e.g. a function or a loop body), V8 will replace it with an optimized version (so called "on-stack replacement").
According to https://wingolog.org/archives/2011/06/08/what-does-v8-do-with-that-loop:
V8 always compiles JavaScript to native code. The first time V8 sees a
piece of code, it compiles it quickly but without optimizing it. The
initial unoptimized code is fully general, handling all of the various
cases that one might see, and also includes some type-feedback code,
recording what types are being seen at various points in the
procedure.
At startup, V8 spawns off a profiling thread. If it notices that a
particular unoptimized procedure is hot, it collects the recorded type
feedback data for that procedure and uses it to compile an optimized
version of the procedure. The old unoptimized code is then replaced
with the new optimized code, and the process continues
Other modern JS engines identify such hotspots and optimize them as well, in a similar fashion.
how does the jit compiler work in JAVASCRIPT ???
when we only have a 1 compilation phase which declares all of our variables and functions (during the creation of the glbal execution context ?o
...when we only have a 1 compilation phase which declares all of our variables and functions...
That's where you're going wrong. :-) Modern JavaScript engines don't have a single compilation phase. Instead, they do an initial pass through the code using something really fast, and then for code that gets reused enough to make it worthwhile, they apply an optimizer to rewrite the code in place with faster code.
In Chrome's V8, the first phase used to be a compiler (called Full-codegen) and the second phase (when needed) was an optimizing compiler called Crankshaft, but they've switched to an interpreter called Ignition for the first phase that parses the code, generates bytecode, and executes that, and then for code that makes it worthwhile, they apply an optimizing compiler called TurboFan to the bytecode. (See that blog post for the details.) This was originally to minimize the memory impact of one-off setup code, but it turned out that generating bytecode was faster than generating machine code and startup performance was actually improved as well.
Is there a way to create a "blackbox" function in a browser JavaScript environment, such that calling it does something but it's impossible from the outside world to step through what's going on inside?
To be precise, I'm looking for a way that's
Transparent algorithm-wise: The code itself is visible to anyone who sees the code.
Opaque execution-wise: While you can see the code, it's impossible for a user to step through each step in the function to inspect variables for each step.
I guess what I'm looking for is some sort of a way to create an atomic function which disallows any browser debugger based inspection, for security purposes.
As per my understanding, there is no way to hide the code from the debugger at the time of execution due to JavaScript being a scripting language, and being interpreted at runtime.
Unlike the compiled code, JavaScript's conversion to machine code is held off until the code is actually executes. That's why we defer exposing any sensitive information on the client-side.
And yes, obfuscation is possible through code minification, but still, the code can be interpreted by a user through a bit of hardwork.
With browsers which use the V8 JavaScript engine (JIT compilation), how much of the code is actually compiled into machine code and executed directly? Does it pick out bits or is the whole JavaScript compiled?
Also, during the execution of the compiled code what would happen if I was to assign a function to an object in JavaScript? In typical languages this would be illegal, but I thought this flexibility within JavaScript came from the fact that it was interpreted so no illegal actions were technically executed? But if its compiled what happens in that scenario?
P.S
Sorry, what I mean is what would happen is this compiled code was executed "myObject = myFunction", assuming those variables were declared elsewhere. Would this be a legal assignment?
Many thanks in advance.
I understand that JavaScript is interpreted and not compiled. No problem there. However, I keep reading here that JavaScript is executed "on the fly" and that lines are read one at a time. This idea is confusing me quite a bit when it comes to the following example:
writeToConsole();
function writeToConsole() {
console.log("This line was reached.");
}
For the record, this bit of code will write to the console just fine. Still, how would the browser know of the existence of exampleFunction() if it had not yet reached the function?
In other words, when exactly is this function first interpreted?
First, you make an incorrect assumption: modern JavaScript is compiled. Engines like V8, SpiderMonkey, and Nitro compile JS source into the native machine code of the host platform.
Even in older engines, JavaScript isn't interpreted. They transform source code into bytecode, which the engine's virtual machine executes.
This is actually how things in Java and .NET languages work: When you "compile" your application, you're actually transforming source code into the platform's bytecode, Java bytecode and CIL respectively. Then at runtime, a JIT compiler compiles the bytecode into machine code.
Only very old and simplistic JS engines actually interpret the JavaScript source code, because interpretation is very slow.
So how does JS compilation work? In the first phase, the source text is transformed into an abstract syntax tree (AST), a data structure that represents your code in a format that machines can deal with. Conceptually, this is much like how HTML text is transformed into its DOM representation, which is what your code actually works with.
In order to generate an AST, the engine must deal with an input of raw bytes. This is typically done by a lexical analyzer. The lexer does not really read the file "line-by-line"; rather it reads byte-by-byte, using the rules of the language's syntax to convert the source text into tokens. The lexer then passes the stream of tokens to a parser, which is what actually builds the AST. The parser verifies that the tokens form a valid sequence.
You should now be able to see plainly why a syntax error prevents your code from working at all. If unexpected characters appear in your source text, the engine cannot generate a complete AST, and it cannot move on to the next phase.
Once an engine has an AST:
An interpreter might simply begin executing the instructions directly from the AST. This is very slow.
A JS VM implementation uses the AST to generate bytecode, then begins executing the bytecode.
A compiler uses the AST to generate machine code, which the CPU executes.
So you should now be able to see that at minimum, JS execution happens in two phases.
However, the phases of execution really have no impact on why your example works. It works because of the rules that define how JavaScript programs are to be evaluated and executed. The rules could just as easily be written in a way such that your example would not work, with no impact on how the engine itself actually interprets/compiles source code.
Specifically, JavaScript has a feature commonly known as hoisting. In order to understand hoisting, you must understand the difference between a function declaration and a function expression.
Simply, a function declaration is when you declare a new function that will be called elsewhere:
function foo() {
}
A function expression is when you use the function keyword in any place that expects an expression, such as variable assignment or in an argument:
var foo = function() { };
$.get('/something', function() { /* callback */ });
JavaScript mandates that function declarations (the first type) be assigned to variable names at the beginning of an execution context, regardless of where the declaration appears in source text (of the context). An execution context is roughly equatable to scope – in plain terms, the code inside a function, or the very top of your script if not inside a function.
This can lead to very curious behavior:
var foo = function() { console.log('bar'); };
function foo() { console.log('baz'); }
foo();
What would you expect to be logged to the console? If you simply read the code linearly, you might think baz. However, it will actually log bar, because the declaration of foo is hoisted above the expression that assigns to foo.
So to conclude:
JS source code is never "read" line-by-line.
JS source code is actually compiled (in the true sense of the word) in modern browsers.
Engines compile code in multiple passes.
The behavior is your example is a byproduct of the rules of the JavaScript language, not how it is compiled or interpreted.
All functions will be examined first by the browser before any code is executed.
However,
var foo = function(){};
This will not be examined, and thus the following will throw a TypeError: undefined is not a function
foo();
var foo = function(){};
It does take 2 passes. The first pass parses the syntax tree, a part of which is performing hoisting. That hoisting is what makes your posted code work. Hoisting moves any var or named function declarations function fn(){} (but not function expressions fn = function(){}) to the top of the function they appear in.
The second pass executes the parsed, hoisted, and in some engines compiled, source code tree.
Check out this example. It shows how a syntax error can prevent all execution of your script by throwing a wrench in the first pass, which prevents the second pass (actual code execution) from ever happening.
var validCode = function() {
alert('valid code ran!');
};
validCode();
// on purpose syntax error after valid code that could run
syntax(Error(
http://jsfiddle.net/Z86rj/
No alert() occurs here. The first pass parsing fails, and no code executes.
The script is first parsed, then interpreted, and then executed. When the first statement (writeToConsole();) is executed, the function declaration has already been interpreted.
Since all variable and function declarations are hoisted in the current scope (in your case, the global script scope), you will be able to call a function that was declared below.
JavaScript is actually interpreted line by line. BUT, before it's executed, there is a first pass made by the compiler, reading certain things in (pretty geeky, have a look at this: https://www.youtube.com/watch?v=UJPdhx5zTaw if you're really interested).
The point is, JavaScript will be first "read" by the compiler, who stores functions defined as function foo(){...} already. You can call those ones at any given time in the script, given you are calling them from the same or a subordinate scope. What modern compilers also do is preallocate objects, so as a side effect it does make sense to strongly type your variables for the matter of performance.
var foo = function(){...} will not be stored by the compiler, due to the fact that JavaScript is loosely typed and the type of a variable could change during execution time.
The javascript engine create a execution context before executing your code. The execution context is created mainly in two phases:
Creation phase
Excecution phase
Creation Phase
In the creation phase we have the Global object, this and outer environment reference.In the creation phase as the parser runs through the code and begins to setup what we have written for translation, it recognizes where we have created variables and where we have created function. Basically it setup memory space for variable and functions Hoisting.
Execution Phase
In this the code is run line by line(interpreting, converting, compiling and executing it on the computer).
consider the following example, in this we are able to call the function b even before its declaration. This is because the javascript engine already knows the existence of the function b. And this is also referred to as hoisting in javascript.
b();
function b() {
console.log("I have been hoisted");
}