Equivalent terminology for 'compile time' in Javascript - javascript

The term compile time is used with compiled languages (such as C++) to indicate the point in which source code is going through the compilation process.
The term runtime is used to indicate the point in which the application is opened and being run by a user.
If, for example, we wrote a simple game that rendered terrain based on some list of vertices... if this terrain data was fetched from a server, I might say that the state of the terrain is unknown until runtime. However if it was envisioned that we'd only have one terrain 'model,' and configured that directly in the source code, I might say the state of the terrain is known at compile time (would I be wrong in saying this?).
In Javascript, what would the equivalent terminology be for compile time? My own solution was to call it design time, however I'd be interested to know if there is correct terminology for this.

It might make more sense, in the case of your example, to just say that it is 'hard-coded', as this seems to be more accurate for what you are describing. Things that are hard-coded are always known at compile-time, but things known at compile-time are not necessarily hard-coded (in C++, for example, they can be generated with constexpr functions, or injected using build parameters).
The closest thing to 'compile-time' in Javascript I would probably call 'build-time', as you often have some sort of building step in Javascript, whether this a heavyweight build process using WebPack, just simple minification, or even just collecting a particular version of your application's files into some sort of distributable package. Even if you're not actually performing such a step at all, I think people would generally understand what was meant by this.

Depends on the implementation, but some engines have "just in time" (JIT) compilation. See JavaScript Just In Time compilation.
However, the things that you can do as the code writer, rather than the engine, are mostly limited to bundling and minification to reduce fetching all of the scripts that are needed to run your program.
The closest comparison would likely be how you can dynamically and statically link in compiled languages.

There is no real equivalent to "compile time" in Javascript.
A common term to refer to e.g. "hoisting" or variable declarations without an assigned value is "creation phase" (vs. "execution phase").
This works well to explain and understand javascript. However, there not necessarily really is such a specific "phase" happening.
The Language Specification ECMA-262 doesn't use these terms either. Instead, it only uses relative terms, i.e. it specifies what should happen before or after something else, and apparently leaves the implementation to the engine developers.
E.g. commonly explained in the internet in a way like:
a var is declared in the "creation phase", and instatiated in the "execution phase"
But ECMA only specifies it more like this way:
a var (/let/const/...) is created when X, but stays 'undefined' as long as Y, ... (but may not be accessed until Z, ...)
Examples for such relative terms:
ECMA-262, 11th, chapter 13.3.2:
Var variables are created when their containing Lexical Environment is instantiated ...
... is assigned the value ... when the VariableDeclaration is executed, not
when the variable is created
ECMA-262, 11th, chapter 8.1:
a new Lexical Environment is created each time such code is evaluated

Related

How actually is the features that are not available in JS is achieved using TS as TS is ultimately compiled to JS?

I was learning TS after JS and it is said that many features that are not in JS like types and all is achieved using TS. But ultimately TS is compiled down to JS. So how is this possible? How features that are not available in a language is achieved using another one if latter one is finally converted to 1st one?
So as stated in comments, typescript doesn't do anything at runtime. After transpilation all of the type information is gone for good. The point of typescript is just to check your code before-hand and find potential errors, that may cause problem when executing the resulting javascript code. All of it's features that are not part of javascript are erased after the checks are performed. private and public are also erased, the only reason they are there is that in your code you cannot use them. But it's just a "recommendation", you can totally ignore it (because, again, private doesn't exist at runtime). For example you can do something like this:
class Foo {
private bar() {}
}
;(new Foo() as any).bar()
Or even
class Foo {
private bar() {}
}
// #ts-ignore
new Foo().bar()
And here you are, you've successfully tricked the typescript compiler and this code will totally work after transpilation, even though the bar method is private and is not supposed to be accessible.
Speaking about "are all high level languages have type system like typescript?". Well, I'd not say so.
Take C for example. There types also don't exist at runtime per se. When the program is compiled, assembled an executed, everything is just a sequence of ones and zeroes, computer doesn't care if a memory location holds a string or a boolean or whatever, everything is just a sequence of bits. However the types are essential for your program to work, because the type defines, how many bytes in memory are considered a single variable. Like if you define an integer variable, you let the compiler know, that this variable will occupy 4 bytes in memory and that when, for example, adding a value to this variable, it should update all 4 bytes. If you define a char variable, it knows to update only 1 byte.
But these types don't really exist at runtime, you can totally use some pointer shenanigans to trick the compiler into thinking char variable you define is actually an integer. Will it cause problems? A lot. Is it cool? Heck yes. Now every time you add a number to this variable, your program will update 4 bytes instead of one, probably erasing some important information in these 3 bytes that don't belong to your variable, good luck debugging.
With other languages it's a little different, like Java abstracts away this pointers trickery, so you can't trick the compiler as easily. But still, variables of different types generate different byte code after compilation.
So in some languages (like C and Java) types actually impact how your program works (like how many bytes a variable occupies), but in typescript it doesn't. You could always just use any and disable type checking for any piece of your code, if the algorithm is correct, it will still work. Not the case in C though

Why is accessing myInstance.property1.subproperty2.subproperty3 costly in JavaScript but free in C++?

I have always understood it to be a cost-savings operation in JavaScript to avoid repeatedly referencing a nested property on an object. Instead of writing a.b.c.d over and over, you would favor let x = a.b.c.d; and then use x (what I've often heard colloquially called "caching the reference.")
It recently came up in conversation with a friend that such a thing would be completely unnecessary and foolish in C++.
Is that true? If so, why? I guess it has to do with the difference in the underlying language implementation between a C++ object and a JavaScript object, but what is the difference exactly?
JavaScript objects are closer to C++'s std::map (or std::unordered_map) than they are to C++ classes.
C++ has the advantage of having separate compilation and run steps. The compiler can really take as long as it likes to analyze large chunks of your program and heavily optimize them. When you're writing C++ you aren't really writing a program for the CPU to execute. You're describing the behavior of a program and the compiler will use that description to come up with a program for you. Your browser's JavaScript runtime (likely a JIT compiler) simply doesn't have the time to do the same level of analysis and optimization. It has to compile and run your program quickly enough that users don't perceive any delay. That's not to say a JavaScript runtime won't do any optimization, but it will tend to be more incremental and localized than what a C++ compiler that takes 20 minutes to compile a program can do.
All of the attributes of a C++ class are known at compile time. When you access an attribute of an object in C++, the compiler will resolve that access at compile time; likely to a handful of memory loads or a single function call instruction. Since it's all resolved at compile time, it doesn't matter how deeply an attribute lookup is nested. The runtime performance will be the same. Additionally, the compiler will do that sort of memorization for you, likely by keeping a repeatedly-accessed attribute in a register.
The same is not true of JavaScript. JavaScript objects don't have a defined set of properties. They can be added and removed throughout the lifetime of the object. That means that the JavaScript runtime has to track an object's properties using some sort of associative data structure (likely a hash table). When you request an attribute of an object, the runtime has to look through that data structure to find the value that you want, and it has to do that lookup for every level of nesting.

Are internal slot and internal methods actually implemented by JavaScript engines?

I was reading ECMA2019 (the same is true in ES6 too), where I found:
Each object in an ECMAScript engine is associated with a set of
internal methods that defines its runtime behaviour. These internal
methods are not part of the ECMAScript language. They are defined by
this specification purely for expository purposes. However, each
object within an implementation of ECMAScript must behave as specified
by the internal methods associated with it. The exact manner in which
this is accomplished is determined by the implementation.
I also found these Stack Overflow question1 and question2 and that their answers don't seem to give me the answer I am looking for.
My question is simple. If JavaScript engines decide not to implement some of them, then how would they ensure this statement of above spec -
However, each object within an implementation of ECMAScript must
behave as specified by the internal methods associated with it.
Let us take an example:
[[GetPrototypeOf]] , [[Get]] , [[Set]] , [[GetOwnProperty]] etc are essential internal methods. If a JavaScript engine refuses to implement them, how does it achieve this functionality? Clearly they have to implement it, just that they can choose to have different method name and different method signature as it is not enforced by spec on them?
Where am I wrong?
Similarly for internal slots too? If they don't have internal variables storing that state, how on earth will they maintain the state of that object when asked?
EDIT : I will add more details to clarify my question. Let us take an example of Object.getPrototypeOf(). This is an API for internal behaviour [[GetPrototypeOf]] and there are possible algorithm for implementing it. The question is not possible ways to implement it a behaviour - its about having a behaviour or not ! and still satisfying the spec overall object behaviour.
V8 developer here. I think this question has mostly been answered already in the comments, so I'll just summarize.
Are internal slot and internal methods actually implemented by JavaScript engines?
Generally not; the engine simply behaves as if its internals were structured in this way. Some parts of an implementation might be very close to the spec's structure, if it's convenient.
One way to phrase it would be: you could implement a JavaScript engine by first faithfully translating the spec text to code (in whichever language you choose to use for your engine), and then you'd be allowed to refactor the invisible internals in any way you want (e.g.: inline functions, or split them up, or organize them as a helper class, or add a fast path or a cache, or generally turn the code inside out, etc). Which isn't surprising, really: as long as the observable behavior remains the same, any program is allowed to refactor its internals. What the ECMAScript is making clear at that point is simply that the "internal slots" really are guaranteed to always be internal and not observable.
[[[Get]] etc] are essential internal methods. If a JavaScript engine refuses to implement them, how does it achieve this functionality?
It's not about refusing to implement something. You can usually implement functionality in many different ways, i.e. with many different ways of structuring your code and your objects. Engines are free to structure their code and objects any way they want, as long as the resulting observable behavior is as specified.
Let us take an example of Object.getPrototypeOf(). This is an API for internal behaviour [[GetPrototypeOf]]
Not quite. Object.getPrototypeOf is a public function that's specified to behave in a certain way. The way the spec describes it is that it must *behave as if there were an internal slot [[GetPrototypeOf]].
You seem to have trouble imagining an alternative way. Well, in many cases, engines will probably choose to have an implementation that's very close to having those internal slots -- perhaps mapped to fields and methods in a C++ class. But it doesn't have to be that way; for example, instead of class methods, there could be free functions: GetPrototypeImpl(internal::Object object) rather than internal::Object::GetPrototypeImpl(). Or instead of an inheritance/hierarchy structure, the engine could use switch-statements over types.
One of the most common ways in which engines' implementations deviate from the structure defined by the spec's internal slots is by having additional fast paths. Typically, a fast path performs a few checks to see if it is applicable, and then does the simple, common case; if the applicability check fails, it falls back to a slower, more complete implementation, that might be much closer to the spec's structure. Or maybe neither function on its own contains the complete spec'ed behavior: you could have GetPrototypeFromRegularObject and GetPrototypeFromProxy plus a wrapper dispatching to the right one, and those all together behave like the spec's hypothetical system of having a [[GetPrototypeOf]] slot on both proxies and regular objects. All of that is perfectly okay because from the outside you can't see a difference in behavior -- all you can see is Object.getPrototypeOf.
One particular example of a fast path is a compiler. If you implemented object behaviors as (private) methods, and loaded and called those methods every time, then your implementation would be extremely slow. Modern engines compile JavaScript functions to bytecode or even machine code, and that code will behave as if you had loaded and called an internal function with the given behavior, but it (usually) will not actually call any such functions. For example, optimized code for an array[index] access should only be a few machine instructions (type check, bounds check, memory load), there should be no call to a [[Get]] involved.
Another very common example is object types. The spec typically uses wording like "if the object has a [[StringData]] internal slot, then ..."; an engine typically replaces that with "if the object's type is what I've chosen for representing strings internally, then ...". Again, the difference is not observable from the outside: Strings behave as if they had a [[StringData]] internal slot, but (in V8 at least) they don't have such a slot, they simply have an appropriate object type that identifies them as strings, and objects with string type know where their character payload is, they don't need any special slot for that.
Edit: forgot to mention: see also https://v8.dev/blog/understanding-ecmascript-part-1 for another way to explain it.

JavaScript compilation in V8

In the V8 home (the Google's JavaScript engine) we read this:
V8 compiles and executes JavaScript source code
Does it mean that JavaScript is not an interpreted language in V8?
Does V8 use a just-in-time compilation approach for JavaScript?
Edit: There is another existing question which already address my first question, but not the second.
Does it mean that JavaScript is not an interpreted language in V8?
The answer to this is "it depends".
Historically V8 has compiled directly to machine code using its "full-codegen" compiler, which produces unoptimized code which uses inline caching to implement most operations such as arithmetic operations, load and stores of variables and properties, etc.
The code generated by full-codegen keeps track of how "hot" each function is, by adjusting a counter when the function is called and when it jumps back to the top of loops.
It also keeps track of the types of the variables used in each expression.
If it determines that a function (or part of a function) is very hot, and it has collected enough type information, it triggers the "Crankshaft" compiler which generates much better code.
However, the V8 developers are actively working on moving to a different system where they start off with an interpreter called "Ignition" and then use a compiler called "Turbofan" to produce optimized code for hot functions.
Here are a couple of posts from the V8 developers blog describing this:
Firing up the Ignition Interpreter
Help us test the future of V8
Does V8 use a just-in-time compilation approach for JavaScript?
Yes, in a number of ways.
Firstly, it has a lazy parsing and lazy compilation mechanism. This means that when it parses a Javascript source file it parses the outermost scope eagerly, generating the full-codegen code immediately.
However, for functions defined within the file, it skips over them and just records the name of the function and the location of its source code. It generates a dummy function which simply calls into the V8 runtime to trigger the actual compilation of the function.
Secondly, it has a two stage compiler pipeline as described above, using either full-codegen+crankshaft or ignition+turbofan.
When the compilation is triggered it will initially generate unoptimized code or ignition bytecode (which it can do very quickly), and then later if the code is hot it triggers an optimized re-compilation (which is much slower but generates much better code).

Dart vs JavaScript - Are they compiled or interpreted languages?

Is Dart considered to be a compiled or an interpreted language?
The same question holds for JavaScript.
The reason for the question:
I've been watching an interview with the founders of dart, and in 7:10 Lars Bak said that:
"When you [...] in a JavaScript program, you actually execute JavaScript before you start running the real program. In Dart, you don't execute anything before the first instruction in main is being executed".
It sounded to me that he's saying that JavaScript is a compiled language while Dart is an interpreted language. Is it true?
Isn't the Dart VM a compiler?
Depends on the definition of "interpreted" and "compiled" language. And even then, it always depends on the implementation.
What Lars meant is that JavaScript builds its class structures (and other global state) by executing code. In Dart the global state is described by the language syntax and thus only needs parsing (and even then most of it can be skipped first). As a consequence Dart programs can start executing "real" code faster than JavaScript programs.
This obviously only holds for the Dart VM, since programs that have been compiled to JavaScript must use JavaScript mechanisms to build their classes.
Edit (more details):
Take, for example, the following extremely simple class A:
In Dart:
class A {
final x;
A(this.x);
foo(y) => y + x;
}
In JavaScript:
function A(x) { this.x = x; }
A.prototype.foo = function(y) { return y + this.x; }
When the Dart VM starts up it starts by going through the program. It sees the class keyword, reads the class-name (A) and could then simply skip to the end of the class (by counting opening and closing braces, making sure they are not in strings). It does not care for the contents of A, until A is actually instantiated. Now, in reality, it actually looks through the class and finds all the members, but it does not read the contents of methods until they are needed. In any case: it does this in a very fast processing step.
In JavaScript things get more complicated: a fast VM can skip the actual body of the function A (similar to what Dart does), but when it sees A.prototype.foo = ... it needs to execute code to create the prototype object. That is, it needs to allocate a function object (A), look up its prototype property, change this object (adding a new property) with a new function object. In other words: in order to even see that you have a class you need to execute code.
Dart as programming language in its primary implementation can be presented as a virtual machine (VM), which is the runtime of programs written in that language.
Current virtual machine implemented as the "just-in-time" (JIT) runtime environment engine.
This means that program not interpreted but compiled. But this compilation process (translating source code to machine instructions) is stretched in time for an unknown period.
This allows virtual machine to defer performing certain operations indefinitely or never performing them.
Assume you have a very big and complex program with a lot of classes which may be never be used in current short lifetime session of program execution.
JIT compilation allow not compile all unused classes but just parse it to special tokens.
These tokens later will be used (on demand) for translating them to intermadiate language for constructing machine code.
This process is transparent for user of program. Compiled (to machine code) only that source code that required for the correct working of the program.
Some source code can be never compiled what save a lot of time.
Conclusion:
If Dart language used in its primary state as virtual machine then it compiled to machine code.
Dart compiles into JavaScript, and JavaScript is an interpreted language. Usually, by 'compiled' languages one understands languages which are compiled into platform-specific machine code, run right on the CPU and don't require an interpreter to run, which is not the case for neither JS nor Dart. So I would say that both JS and Dart are interpreted.

Categories

Resources