Array.prototype.push

I’m always amazed by the excellent readability of V8’s source code. I think everyone should have a rough idea about where to look for specific implementation details of the most common JavaScript functions.

As an example, let’s look at how Array#push is implemented in V8. V8 implements all (well, most) Array.prototype functions as BIFs in src/js/array.js:

// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Appends the arguments to the end of the array and returns the new
// length of the array. See ECMA-262, section 15.4.4.7.
function ArrayPush() {
  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");

  var array = TO_OBJECT(this);
  var n = TO_LENGTH(array.length);
  var m = arguments.length;

  // Subtract n from kMaxSafeInteger rather than testing m + n >
  // kMaxSafeInteger. n may already be kMaxSafeInteger. In that case adding
  // e.g., 1 would not be safe.
  if (m > kMaxSafeInteger - n) throw MakeTypeError(kPushPastSafeLength, m, n);

  for (var i = 0; i < m; i++) {
    array[i+n] = arguments[i];
  }

  var new_length = n + m;
  array.length = new_length;
  return new_length;
}

Pretty readable, right?

CHECK_OBJECT_COERCIBLE is a macro. The V8 codebase uses quite a lot of custom macros defined in macros.py:

# Macro for ES6 CheckObjectCoercible
# Will throw a TypeError of the form "[functionName] called on null or undefined".
macro CHECK_OBJECT_COERCIBLE(arg, functionName) = if (IS_NULL(%IS_VAR(arg)) || IS_UNDEFINED(arg)) throw MakeTypeError(kCalledOnNullOrUndefined, functionName);

CHECK_OBJECT_COERCIBLE throws an error if Array.prototype.push is called on null or undefined. Makes sense, right? You can easily try this out in your console:

Array.prototype.push.call(null, 1)
  // #=> throws TypeError: Array.prototype.push called on null or undefined

IS_NULL and IS_UNDEFINED are macros as well. Interestingly V8 never seems to use undefined, but always void 0. I assume this is because you used to be able to globally override window.undefined.

The rest is pretty intuitive…

Disclaimer: I’m not working on V8.


Further reading:

 
8
Kudos
 
8
Kudos

Now read this

Storing nested objects in Redis

Since Redis supports the usage of a Hash Tables, one dimensional JavaScript-like objects can be modeled it quite easily. The problem though is that hash tables can’t be nested - at least in Redis. Assume we have the following JavaScript... Continue →