Changed Array.prototype.sort to use quick sort.
Fixed code generation issue where leaving a finally block with break or continue would accumulate elements on the expression stack (issue 86).
Made sure that the name accessor on functions returns the expected names for builtin JavaScript functions and C++ callback functions.
Added fast case code for extending the property storage array of JavaScript objects.
Ported switch statement optimizations introduced in version 0.3.3 to the ARM code generator.
Allowed GCC to use strict-aliasing rules when compiling.
Improved performance of arguments object allocation by taking care of arguments adaptor frames in the generated code.
Updated the V8 benchmark suite to version 2.
git-svn-id: http://v8.googlecode.com/svn/trunk@439 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/v8natives.js b/src/v8natives.js
index f65de4f..64b2610 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -25,8 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
// This file relies on the fact that the following declarations have been made
+//
// in runtime.js:
// const $Object = global.Object;
// const $Boolean = global.Boolean;
@@ -34,37 +34,45 @@
// const $Function = global.Function;
// const $Array = global.Array;
// const $NaN = 0/0;
+//
+// in math.js:
+// const $floor = MathFloor
+
+const $isNaN = GlobalIsNaN;
+const $isFinite = GlobalIsFinite;
+
+// ----------------------------------------------------------------------------
-// ECMA 262 - 15.1.1.1.
-%AddProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
+// Helper function used to install functions on objects.
+function InstallFunctions(object, attributes, functions) {
+ for (var i = 0; i < functions.length; i += 2) {
+ var key = functions[i];
+ var f = functions[i + 1];
+ %FunctionSetName(f, key);
+ %SetProperty(object, key, f, attributes);
+ }
+}
-// ECMA-262 - 15.1.1.2.
-%AddProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
-
-
-// ECMA-262 - 15.1.1.3.
-%AddProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
+// ----------------------------------------------------------------------------
// ECMA 262 - 15.1.4
-function $isNaN(number) {
+function GlobalIsNaN(number) {
var n = ToNumber(number);
return NUMBER_IS_NAN(n);
-};
-%AddProperty(global, "isNaN", $isNaN, DONT_ENUM);
+}
// ECMA 262 - 15.1.5
-function $isFinite(number) {
+function GlobalIsFinite(number) {
return %NumberIsFinite(ToNumber(number));
-};
-%AddProperty(global, "isFinite", $isFinite, DONT_ENUM);
+}
// ECMA-262 - 15.1.2.2
-%AddProperty(global, "parseInt", function(string, radix) {
+function GlobalParseInt(string, radix) {
if (radix === void 0) {
radix = 0;
// Some people use parseInt instead of Math.floor. This
@@ -75,9 +83,9 @@
if (%_IsSmi(string)) return string;
if (IS_NUMBER(string)) {
if (string >= 0.01 && string < 1e9)
- return $Math_floor(string);
+ return $floor(string);
if (string <= -0.01 && string > -1e9)
- return - $Math_floor(-string);
+ return - $floor(-string);
}
} else {
radix = TO_INT32(radix);
@@ -85,13 +93,61 @@
return $NaN;
}
return %StringParseInt(ToString(string), radix);
-}, DONT_ENUM);
+}
// ECMA-262 - 15.1.2.3
-%AddProperty(global, "parseFloat", function(string) {
+function GlobalParseFloat(string) {
return %StringParseFloat(ToString(string));
-}, DONT_ENUM);
+}
+
+
+function GlobalEval(x) {
+ if (!IS_STRING(x)) return x;
+
+ var f = %CompileString(x, 0, true);
+ if (!IS_FUNCTION(f)) return f;
+
+ return f.call(%EvalReceiver(this));
+}
+
+
+// execScript for IE compatibility.
+function GlobalExecScript(expr, lang) {
+ // NOTE: We don't care about the character casing.
+ if (!lang || /javascript/i.test(lang)) {
+ var f = %CompileString(ToString(expr), 0, false);
+ f.call(global);
+ }
+ return null;
+}
+
+
+// ----------------------------------------------------------------------------
+
+
+function SetupGlobal() {
+ // ECMA 262 - 15.1.1.1.
+ %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
+
+ // ECMA-262 - 15.1.1.2.
+ %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
+
+ // ECMA-262 - 15.1.1.3.
+ %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
+
+ // Setup non-enumerable function on the global object.
+ InstallFunctions(global, DONT_ENUM, $Array(
+ "isNaN", GlobalIsNaN,
+ "isFinite", GlobalIsFinite,
+ "parseInt", GlobalParseInt,
+ "parseFloat", GlobalParseFloat,
+ "eval", GlobalEval,
+ "execScript", GlobalExecScript
+ ));
+}
+
+SetupGlobal();
// ----------------------------------------------------------------------------
@@ -108,80 +164,93 @@
%FunctionSetPrototype($Boolean, new $Boolean(false));
-%AddProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
+%SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
// ----------------------------------------------------------------------------
// Object
$Object.prototype.constructor = $Object;
-%AddProperty($Object.prototype, "toString", function() {
+// ECMA-262 - 15.2.4.2
+function ObjectToString() {
var c = %ClassOf(this);
// Hide Arguments from the outside.
if (c === 'Arguments') c = 'Object';
return "[object " + c + "]";
-}, DONT_ENUM);
+}
-// ECMA-262, section 15.2.4.3, page 84.
-%AddProperty($Object.prototype, "toLocaleString", function() {
+// ECMA-262 - 15.2.4.3
+function ObjectToLocaleString() {
return this.toString();
-}, DONT_ENUM);
+}
-// ECMA-262, section 15.2.4.4, page 85.
-%AddProperty($Object.prototype, "valueOf", function() {
+// ECMA-262 - 15.2.4.4
+function ObjectValueOf() {
return this;
-}, DONT_ENUM);
+}
-// ECMA-262, section 15.2.4.5, page 85.
-%AddProperty($Object.prototype, "hasOwnProperty", function(V) {
+// ECMA-262 - 15.2.4.5
+function ObjectHasOwnProperty(V) {
return %HasLocalProperty(ToObject(this), ToString(V));
-}, DONT_ENUM);
+}
-// ECMA-262, section 15.2.4.6, page 85.
-%AddProperty($Object.prototype, "isPrototypeOf", function(V) {
+// ECMA-262 - 15.2.4.6
+function ObjectIsPrototypeOf(V) {
if (!IS_OBJECT(V) && !IS_FUNCTION(V)) return false;
return %IsInPrototypeChain(this, V);
-}, DONT_ENUM);
+}
-// ECMA-262, section 15.2.4.6, page 85.
-%AddProperty($Object.prototype, "propertyIsEnumerable", function(V) {
+// ECMA-262 - 15.2.4.6
+function ObjectPropertyIsEnumerable(V) {
if (this == null) return false;
if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false;
return %IsPropertyEnumerable(this, ToString(V));
-}, DONT_ENUM);
+}
// Extensions for providing property getters and setters.
-%AddProperty($Object.prototype, "__defineGetter__", function(name, fun) {
- if (this == null) throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
- if (!IS_FUNCTION(fun)) throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
+function ObjectDefineGetter(name, fun) {
+ if (this == null) {
+ throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
+ }
+ if (!IS_FUNCTION(fun)) {
+ throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
+ }
return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun);
-}, DONT_ENUM);
+}
-
-%AddProperty($Object.prototype, "__lookupGetter__", function(name) {
- if (this == null) throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
+function ObjectLookupGetter(name) {
+ if (this == null) {
+ throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
+ }
return %LookupAccessor(ToObject(this), ToString(name), GETTER);
-}, DONT_ENUM);
+}
-%AddProperty($Object.prototype, "__defineSetter__", function(name, fun) {
- if (this == null) throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
- if (!IS_FUNCTION(fun)) throw new $TypeError('Object.prototype.__defineSetter__: Expecting function');
+function ObjectDefineSetter(name, fun) {
+ if (this == null) {
+ throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
+ }
+ if (!IS_FUNCTION(fun)) {
+ throw new $TypeError(
+ 'Object.prototype.__defineSetter__: Expecting function');
+ }
return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun);
-}, DONT_ENUM);
+}
-%AddProperty($Object.prototype, "__lookupSetter__", function(name) {
- if (this == null) throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
+function ObjectLookupSetter(name) {
+ if (this == null) {
+ throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
+ }
return %LookupAccessor(ToObject(this), ToString(name), SETTER);
-}, DONT_ENUM);
+}
%SetCode($Object, function(x) {
@@ -196,51 +265,61 @@
// ----------------------------------------------------------------------------
-// Global stuff...
-
-%AddProperty(global, "eval", function(x) {
- if (!IS_STRING(x)) return x;
-
- var f = %CompileString(x, 0, true);
- if (!IS_FUNCTION(f)) return f;
-
- return f.call(%EvalReceiver(this));
-}, DONT_ENUM);
-// execScript for IE compatibility.
-%AddProperty(global, "execScript", function(expr, lang) {
- // NOTE: We don't care about the character casing.
- if (!lang || /javascript/i.test(lang)) {
- var f = %CompileString(ToString(expr), 0, false);
- f.call(global);
- }
- return null;
-}, DONT_ENUM);
+function SetupObject() {
+ // Setup non-enumerable functions on the Object.prototype object.
+ InstallFunctions($Object.prototype, DONT_ENUM, $Array(
+ "toString", ObjectToString,
+ "toLocaleString", ObjectToLocaleString,
+ "valueOf", ObjectValueOf,
+ "hasOwnProperty", ObjectHasOwnProperty,
+ "isPrototypeOf", ObjectIsPrototypeOf,
+ "propertyIsEnumerable", ObjectPropertyIsEnumerable,
+ "__defineGetter__", ObjectDefineGetter,
+ "__lookupGetter__", ObjectLookupGetter,
+ "__defineSetter__", ObjectDefineSetter,
+ "__lookupSetter__", ObjectLookupSetter
+ ));
+}
+
+SetupObject();
// ----------------------------------------------------------------------------
// Boolean
-%AddProperty($Boolean.prototype, "toString", function() {
+function BooleanToString() {
// NOTE: Both Boolean objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262.
if (!IS_BOOLEAN(this) && %ClassOf(this) !== 'Boolean')
throw new $TypeError('Boolean.prototype.toString is not generic');
return ToString(%_ValueOf(this));
-}, DONT_ENUM);
+}
-%AddProperty($Boolean.prototype, "valueOf", function() {
+function BooleanValueOf() {
// NOTE: Both Boolean objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262.
if (!IS_BOOLEAN(this) && %ClassOf(this) !== 'Boolean')
throw new $TypeError('Boolean.prototype.valueOf is not generic');
return %_ValueOf(this);
-}, DONT_ENUM);
+}
// ----------------------------------------------------------------------------
+
+
+function SetupBoolean() {
+ InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
+ "toString", BooleanToString,
+ "valueOf", BooleanValueOf
+ ));
+}
+
+SetupBoolean();
+
+// ----------------------------------------------------------------------------
// Number
// Set the Number function and constructor.
@@ -255,25 +334,8 @@
%FunctionSetPrototype($Number, new $Number(0));
-%AddProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
-
-// ECMA-262 section 15.7.3.1.
-%AddProperty($Number, "MAX_VALUE", 1.7976931348623157e+308, DONT_ENUM | DONT_DELETE | READ_ONLY);
-
-// ECMA-262 section 15.7.3.2.
-%AddProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
-
-// ECMA-262 section 15.7.3.3.
-%AddProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
-
-// ECMA-262 section 15.7.3.4.
-%AddProperty($Number, "NEGATIVE_INFINITY", -1/0, DONT_ENUM | DONT_DELETE | READ_ONLY);
-
-// ECMA-262 section 15.7.3.5.
-%AddProperty($Number, "POSITIVE_INFINITY", 1/0, DONT_ENUM | DONT_DELETE | READ_ONLY);
-
// ECMA-262 section 15.7.4.2.
-%AddProperty($Number.prototype, "toString", function(radix) {
+function NumberToString(radix) {
// NOTE: Both Number objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262.
var number = this;
@@ -295,38 +357,38 @@
}
// Convert the number to a string in the given radix.
return %NumberToRadixString(number, radix);
-}, DONT_ENUM);
+}
// ECMA-262 section 15.7.4.3
-%AddProperty($Number.prototype, "toLocaleString", function() {
+function NumberToLocaleString() {
return this.toString();
-}, DONT_ENUM);
+}
// ECMA-262 section 15.7.4.4
-%AddProperty($Number.prototype, "valueOf", function() {
+function NumberValueOf() {
// NOTE: Both Number objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262.
if (!IS_NUMBER(this) && %ClassOf(this) !== 'Number')
throw new $TypeError('Number.prototype.valueOf is not generic');
return %_ValueOf(this);
-}, DONT_ENUM);
+}
// ECMA-262 section 15.7.4.5
-%AddProperty($Number.prototype, "toFixed", function(fractionDigits) {
+function NumberToFixed(fractionDigits) {
var f = TO_INTEGER(fractionDigits);
if (f < 0 || f > 20) {
throw new $RangeError("toFixed() digits argument must be between 0 and 20");
}
var x = ToNumber(this);
return %NumberToFixed(x, f);
-}, DONT_ENUM);
+}
// ECMA-262 section 15.7.4.6
-%AddProperty($Number.prototype, "toExponential", function(fractionDigits) {
+function NumberToExponential(fractionDigits) {
var f = -1;
if (!IS_UNDEFINED(fractionDigits)) {
f = TO_INTEGER(fractionDigits);
@@ -336,11 +398,11 @@
}
var x = ToNumber(this);
return %NumberToExponential(x, f);
-}, DONT_ENUM);
+}
// ECMA-262 section 15.7.4.7
-%AddProperty($Number.prototype, "toPrecision", function(precision) {
+function NumberToPrecision(precision) {
if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
var p = TO_INTEGER(precision);
if (p < 1 || p > 21) {
@@ -348,7 +410,52 @@
}
var x = ToNumber(this);
return %NumberToPrecision(x, p);
-}, DONT_ENUM);
+}
+
+
+// ----------------------------------------------------------------------------
+
+function SetupNumber() {
+ // Setup the constructor property on the Number prototype object.
+ %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
+
+ // ECMA-262 section 15.7.3.1.
+ %SetProperty($Number,
+ "MAX_VALUE",
+ 1.7976931348623157e+308,
+ DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+ // ECMA-262 section 15.7.3.2.
+ %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+ // ECMA-262 section 15.7.3.3.
+ %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+ // ECMA-262 section 15.7.3.4.
+ %SetProperty($Number,
+ "NEGATIVE_INFINITY",
+ -1/0,
+ DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+ // ECMA-262 section 15.7.3.5.
+ %SetProperty($Number,
+ "POSITIVE_INFINITY",
+ 1/0,
+ DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+ // Setup non-enumerable functions on the Number prototype object.
+ InstallFunctions($Number.prototype, DONT_ENUM, $Array(
+ "toString", NumberToString,
+ "toLocaleString", NumberToLocaleString,
+ "valueOf", NumberValueOf,
+ "toFixed", NumberToFixed,
+ "toExponential", NumberToExponential,
+ "toPrecision", NumberToPrecision
+ ));
+}
+
+SetupNumber();
+
// ----------------------------------------------------------------------------
@@ -356,7 +463,6 @@
$Function.prototype.constructor = $Function;
-
function FunctionSourceString(func) {
// NOTE: Both Function objects and values can enter here as
// 'func'. This is not as dictated by ECMA-262.
@@ -382,12 +488,12 @@
if (source.match(regexp)) source = source.replace(regexp, "$1");
var name = %FunctionGetName(func);
return 'function ' + name + source;
-};
+}
-%AddProperty($Function.prototype, "toString", function() {
+function FunctionToString() {
return FunctionSourceString(this);
-}, DONT_ENUM);
+}
function NewFunction(arg1) { // length == 1
@@ -413,6 +519,17 @@
var f = %CompileString(source, -1, false)();
%FunctionSetName(f, "anonymous");
return %SetNewFunctionAttributes(f);
-};
+}
%SetCode($Function, NewFunction);
+
+// ----------------------------------------------------------------------------
+
+function SetupFunction() {
+ InstallFunctions($Function.prototype, DONT_ENUM, $Array(
+ "toString", FunctionToString
+ ));
+}
+
+SetupFunction();
+