Roll V8 back to 3.6

Roll back to V8 3.6 to fix x86 build, we don't have ucontext.h.

This reverts commits:
5d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0b
c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9
592a9fc1d8ea420377a2e7efd0600e20b058be2b

Bug: 5688872
Change-Id: Ic961bb5e65b778e98bbfb71cce71d99fa949e995
diff --git a/src/v8natives.js b/src/v8natives.js
index f1e8084..588bdb2 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -1,4 +1,4 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -28,18 +28,18 @@
 // This file relies on the fact that the following declarations have been made
 //
 // in runtime.js:
-// var $Object = global.Object;
-// var $Boolean = global.Boolean;
-// var $Number = global.Number;
-// var $Function = global.Function;
-// var $Array = global.Array;
-// var $NaN = 0/0;
+// const $Object = global.Object;
+// const $Boolean = global.Boolean;
+// const $Number = global.Number;
+// const $Function = global.Function;
+// const $Array = global.Array;
+// const $NaN = 0/0;
 //
 // in math.js:
-// var $floor = MathFloor
+// const $floor = MathFloor
 
-var $isNaN = GlobalIsNaN;
-var $isFinite = GlobalIsFinite;
+const $isNaN = GlobalIsNaN;
+const $isFinite = GlobalIsFinite;
 
 // ----------------------------------------------------------------------------
 
@@ -60,6 +60,18 @@
   %ToFastProperties(object);
 }
 
+// Emulates JSC by installing functions on a hidden prototype that
+// lies above the current object/prototype.  This lets you override
+// functions on String.prototype etc. and then restore the old function
+// with delete.  See http://code.google.com/p/chromium/issues/detail?id=1717
+function InstallFunctionsOnHiddenPrototype(object, attributes, functions) {
+  %CheckIsBootstrapping();
+  var hidden_prototype = new $Object();
+  %SetHiddenPrototype(object, hidden_prototype);
+  InstallFunctions(hidden_prototype, attributes, functions);
+}
+
+
 // Prevents changes to the prototype of a built-infunction.
 // The "prototype" property of the function object is made non-configurable,
 // and the prototype object is made non-extensible. The latter prevents
@@ -127,9 +139,8 @@
     // The spec says ToString should be evaluated before ToInt32.
     string = TO_STRING_INLINE(string);
     radix = TO_INT32(radix);
-    if (!(radix == 0 || (2 <= radix && radix <= 36))) {
+    if (!(radix == 0 || (2 <= radix && radix <= 36)))
       return $NaN;
-    }
   }
 
   if (%_HasCachedArrayIndex(string) &&
@@ -151,23 +162,28 @@
 function GlobalEval(x) {
   if (!IS_STRING(x)) return x;
 
+  var receiver = this;
   var global_receiver = %GlobalReceiver(global);
+
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = global_receiver;
+  }
+
+  var this_is_global_receiver = (receiver === global_receiver);
   var global_is_detached = (global === global_receiver);
 
   // For consistency with JSC we require the global object passed to
   // eval to be the global object from which 'eval' originated. This
   // is not mandated by the spec.
-  // We only throw if the global has been detached, since we need the
-  // receiver as this-value for the call.
-  if (global_is_detached) {
-    throw new $EvalError('The "this" value passed to eval must ' +
+  if (!this_is_global_receiver || global_is_detached) {
+    throw new $EvalError('The "this" object passed to eval must ' +
                          'be the global object from which eval originated');
   }
 
   var f = %CompileString(x);
   if (!IS_FUNCTION(f)) return f;
 
-  return %_CallFunction(global_receiver, f);
+  return %_CallFunction(receiver, f);
 }
 
 
@@ -177,14 +193,13 @@
 function SetUpGlobal() {
   %CheckIsBootstrapping();
   // ECMA 262 - 15.1.1.1.
-  %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
+  %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
 
   // ECMA-262 - 15.1.1.2.
-  %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE | READ_ONLY);
+  %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
 
   // ECMA-262 - 15.1.1.3.
-  %SetProperty(global, "undefined", void 0,
-               DONT_ENUM | DONT_DELETE | READ_ONLY);
+  %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
 
   // Set up non-enumerable function on the global object.
   InstallFunctions(global, DONT_ENUM, $Array(
@@ -284,8 +299,7 @@
     receiver = %GlobalReceiver(global);
   }
   if (!IS_SPEC_FUNCTION(fun)) {
-    throw new $TypeError(
-        'Object.prototype.__defineGetter__: Expecting function');
+    throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
   }
   var desc = new PropertyDescriptor();
   desc.setGet(fun);
@@ -331,9 +345,8 @@
 
 
 function ObjectKeys(obj) {
-  if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.keys"]);
-  }
+  if (!IS_SPEC_OBJECT(obj))
+    throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
   if (%IsJSProxy(obj)) {
     var handler = %GetHandler(obj);
     var names = CallTrap0(handler, "keys", DerivedKeysTrap);
@@ -359,7 +372,6 @@
 
 // ES5 8.10.3.
 function IsGenericDescriptor(desc) {
-  if (IS_UNDEFINED(desc)) return false;
   return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc));
 }
 
@@ -464,7 +476,7 @@
 
 // For Harmony proxies.
 function ToCompletePropertyDescriptor(obj) {
-  var desc = ToPropertyDescriptor(obj);
+  var desc = ToPropertyDescriptor(obj)
   if (IsGenericDescriptor(desc) || IsDataDescriptor(desc)) {
     if (!desc.hasValue()) desc.setValue(void 0);
     if (!desc.hasWritable()) desc.setWritable(false);
@@ -660,21 +672,6 @@
 }
 
 
-// ES5 section 8.12.7.
-function Delete(obj, p, should_throw) {
-  var desc = GetOwnProperty(obj, p);
-  if (IS_UNDEFINED(desc)) return true;
-  if (desc.isConfigurable()) {
-    %DeleteProperty(obj, p, 0);
-    return true;
-  } else if (should_throw) {
-    throw MakeTypeError("define_disallowed", [p]);
-  } else {
-    return;
-  }
-}
-
-
 // Harmony proxies.
 function DefineProxyProperty(obj, p, attributes, should_throw) {
   var handler = %GetHandler(obj);
@@ -692,7 +689,12 @@
 
 
 // ES5 8.12.9.
-function DefineObjectProperty(obj, p, desc, should_throw) {
+function DefineOwnProperty(obj, p, desc, should_throw) {
+  if (%IsJSProxy(obj)) {
+    var attributes = FromGenericPropertyDescriptor(desc);
+    return DefineProxyProperty(obj, p, attributes, should_throw);
+  }
+
   var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p));
   // A false value here means that access checks failed.
   if (current_or_access === false) return void 0;
@@ -706,7 +708,7 @@
     if (should_throw) {
       throw MakeTypeError("define_disallowed", [p]);
     } else {
-      return false;
+      return;
     }
   }
 
@@ -736,7 +738,7 @@
         if (should_throw) {
           throw MakeTypeError("redefine_disallowed", [p]);
         } else {
-          return false;
+          return;
         }
       }
       // Step 8
@@ -746,7 +748,7 @@
           if (should_throw) {
             throw MakeTypeError("redefine_disallowed", [p]);
           } else {
-            return false;
+            return;
           }
         }
         // Step 10a
@@ -755,7 +757,7 @@
             if (should_throw) {
               throw MakeTypeError("redefine_disallowed", [p]);
             } else {
-              return false;
+              return;
             }
           }
           if (!current.isWritable() && desc.hasValue() &&
@@ -763,7 +765,7 @@
             if (should_throw) {
               throw MakeTypeError("redefine_disallowed", [p]);
             } else {
-              return false;
+              return;
             }
           }
         }
@@ -773,14 +775,14 @@
             if (should_throw) {
               throw MakeTypeError("redefine_disallowed", [p]);
             } else {
-              return false;
+              return;
             }
           }
           if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) {
             if (should_throw) {
               throw MakeTypeError("redefine_disallowed", [p]);
             } else {
-              return false;
+              return;
             }
           }
         }
@@ -834,6 +836,10 @@
     }
 
     %DefineOrRedefineDataProperty(obj, p, value, flag);
+  } else if (IsGenericDescriptor(desc)) {
+    // Step 12 - updating an existing accessor property with generic
+    //           descriptor. Changing flags only.
+    %DefineOrRedefineAccessorProperty(obj, p, GETTER, current.getGet(), flag);
   } else {
     // There are 3 cases that lead here:
     // Step 4b - defining a new accessor property.
@@ -841,113 +847,30 @@
     //                 property.
     // Step 12 - updating an existing accessor property with an accessor
     //           descriptor.
-    var getter = desc.hasGetter() ? desc.getGet() : null;
-    var setter = desc.hasSetter() ? desc.getSet() : null;
-    %DefineOrRedefineAccessorProperty(obj, p, getter, setter, flag);
+    if (desc.hasGetter()) {
+      %DefineOrRedefineAccessorProperty(obj, p, GETTER, desc.getGet(), flag);
+    }
+    if (desc.hasSetter()) {
+      %DefineOrRedefineAccessorProperty(obj, p, SETTER, desc.getSet(), flag);
+    }
   }
   return true;
 }
 
 
-// ES5 section 15.4.5.1.
-function DefineArrayProperty(obj, p, desc, should_throw) {
-  // Note that the length of an array is not actually stored as part of the
-  // property, hence we use generated code throughout this function instead of
-  // DefineObjectProperty() to modify its value.
-
-  // Step 3 - Special handling for length property.
-  if (p == "length") {
-    var length = obj.length;
-    if (!desc.hasValue()) {
-      return DefineObjectProperty(obj, "length", desc, should_throw);
-    }
-    var new_length = ToUint32(desc.getValue());
-    if (new_length != ToNumber(desc.getValue())) {
-      throw new $RangeError('defineProperty() array length out of range');
-    }
-    var length_desc = GetOwnProperty(obj, "length");
-    if (new_length != length && !length_desc.isWritable()) {
-      if (should_throw) {
-        throw MakeTypeError("redefine_disallowed", [p]);
-      } else {
-        return false;
-      }
-    }
-    var threw = false;
-    while (new_length < length--) {
-      if (!Delete(obj, ToString(length), false)) {
-        new_length = length + 1;
-        threw = true;
-        break;
-      }
-    }
-    // Make sure the below call to DefineObjectProperty() doesn't overwrite
-    // any magic "length" property by removing the value.
-    obj.length = new_length;
-    desc.value_ = void 0;
-    desc.hasValue_ = false;
-    if (!DefineObjectProperty(obj, "length", desc, should_throw) || threw) {
-      if (should_throw) {
-        throw MakeTypeError("redefine_disallowed", [p]);
-      } else {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // Step 4 - Special handling for array index.
-  var index = ToUint32(p);
-  if (index == ToNumber(p) && index != 4294967295) {
-    var length = obj.length;
-    var length_desc = GetOwnProperty(obj, "length");
-    if ((index >= length && !length_desc.isWritable()) ||
-        !DefineObjectProperty(obj, p, desc, true)) {
-      if (should_throw) {
-        throw MakeTypeError("define_disallowed", [p]);
-      } else {
-        return false;
-      }
-    }
-    if (index >= length) {
-      obj.length = index + 1;
-    }
-    return true;
-  }
-
-  // Step 5 - Fallback to default implementation.
-  return DefineObjectProperty(obj, p, desc, should_throw);
-}
-
-
-// ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies.
-function DefineOwnProperty(obj, p, desc, should_throw) {
-  if (%IsJSProxy(obj)) {
-    var attributes = FromGenericPropertyDescriptor(desc);
-    return DefineProxyProperty(obj, p, attributes, should_throw);
-  } else if (IS_ARRAY(obj)) {
-    return DefineArrayProperty(obj, p, desc, should_throw);
-  } else {
-    return DefineObjectProperty(obj, p, desc, should_throw);
-  }
-}
-
-
 // ES5 section 15.2.3.2.
 function ObjectGetPrototypeOf(obj) {
-  if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.getPrototypeOf"]);
-  }
+  if (!IS_SPEC_OBJECT(obj))
+    throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]);
   return %GetPrototype(obj);
 }
 
 
 // ES5 section 15.2.3.3
 function ObjectGetOwnPropertyDescriptor(obj, p) {
-  if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object",
-                        ["Object.getOwnPropertyDescriptor"]);
-  }
+  if (!IS_SPEC_OBJECT(obj))
+    throw MakeTypeError("obj_ctor_property_non_object",
+                        ["getOwnPropertyDescriptor"]);
   var desc = GetOwnProperty(obj, p);
   return FromPropertyDescriptor(desc);
 }
@@ -960,14 +883,14 @@
   }
   var n = ToUint32(obj.length);
   var array = new $Array(n);
-  var names = {};  // TODO(rossberg): use sets once they are ready.
+  var names = {}
   for (var index = 0; index < n; index++) {
     var s = ToString(obj[index]);
     if (s in names) {
-      throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
+      throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s])
     }
     array[index] = s;
-    names[s] = 0;
+    names.s = 0;
   }
   return array;
 }
@@ -975,9 +898,9 @@
 
 // ES5 section 15.2.3.4.
 function ObjectGetOwnPropertyNames(obj) {
-  if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.getOwnPropertyNames"]);
-  }
+  if (!IS_SPEC_OBJECT(obj))
+    throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"]);
+
   // Special handling for proxies.
   if (%IsJSProxy(obj)) {
     var handler = %GetHandler(obj);
@@ -994,9 +917,8 @@
   if (%GetInterceptorInfo(obj) & 1) {
     var indexedInterceptorNames =
         %GetIndexedInterceptorElementNames(obj);
-    if (indexedInterceptorNames) {
+    if (indexedInterceptorNames)
       propertyNames = propertyNames.concat(indexedInterceptorNames);
-    }
   }
 
   // Find all the named properties.
@@ -1022,9 +944,8 @@
     // We need to check for the exact property value since for intrinsic
     // properties like toString if(propertySet["toString"]) will always
     // succeed.
-    if (propertySet[name] === true) {
+    if (propertySet[name] === true)
       continue;
-    }
     propertySet[name] = true;
     propertyNames[j++] = name;
   }
@@ -1049,7 +970,7 @@
 // ES5 section 15.2.3.6.
 function ObjectDefineProperty(obj, p, attributes) {
   if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.defineProperty"]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]);
   }
   var name = ToString(p);
   if (%IsJSProxy(obj)) {
@@ -1100,17 +1021,14 @@
 
 // ES5 section 15.2.3.7.
 function ObjectDefineProperties(obj, properties) {
-  if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.defineProperties"]);
-  }
+  if (!IS_SPEC_OBJECT(obj))
+    throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]);
   var props = ToObject(properties);
   var names = GetOwnEnumerablePropertyNames(props);
-  var descriptors = new InternalArray();
   for (var i = 0; i < names.length; i++) {
-    descriptors.push(ToPropertyDescriptor(props[names[i]]));
-  }
-  for (var i = 0; i < names.length; i++) {
-    DefineOwnProperty(obj, names[i], descriptors[i], true);
+    var name = names[i];
+    var desc = ToPropertyDescriptor(props[name]);
+    DefineOwnProperty(obj, name, desc, true);
   }
   return obj;
 }
@@ -1124,20 +1042,12 @@
     throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
   }
 
-  if (%IsJSFunctionProxy(obj)) {
+  if (IS_SPEC_FUNCTION(obj)) {
     var callTrap = %GetCallTrap(obj);
     var constructTrap = %GetConstructTrap(obj);
     var code = DelegateCallAndConstruct(callTrap, constructTrap);
     %Fix(obj);  // becomes a regular function
     %SetCode(obj, code);
-    // TODO(rossberg): What about length and other properties? Not specified.
-    // We just put in some half-reasonable defaults for now.
-    var prototype = new $Object();
-    $Object.defineProperty(prototype, "constructor",
-      {value: obj, writable: true, enumerable: false, configurable: true});
-    // TODO(v8:1530): defineProperty does not handle prototype and length.
-    %FunctionSetPrototype(obj, prototype);
-    obj.length = 0;
   } else {
     %Fix(obj);
   }
@@ -1148,7 +1058,7 @@
 // ES5 section 15.2.3.8.
 function ObjectSeal(obj) {
   if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.seal"]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["seal"]);
   }
   if (%IsJSProxy(obj)) {
     ProxyFix(obj);
@@ -1170,7 +1080,7 @@
 // ES5 section 15.2.3.9.
 function ObjectFreeze(obj) {
   if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.freeze"]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["freeze"]);
   }
   if (%IsJSProxy(obj)) {
     ProxyFix(obj);
@@ -1193,7 +1103,7 @@
 // ES5 section 15.2.3.10
 function ObjectPreventExtension(obj) {
   if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.preventExtension"]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]);
   }
   if (%IsJSProxy(obj)) {
     ProxyFix(obj);
@@ -1206,7 +1116,7 @@
 // ES5 section 15.2.3.11
 function ObjectIsSealed(obj) {
   if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.isSealed"]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["isSealed"]);
   }
   if (%IsJSProxy(obj)) {
     return false;
@@ -1227,7 +1137,7 @@
 // ES5 section 15.2.3.12
 function ObjectIsFrozen(obj) {
   if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.isFrozen"]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["isFrozen"]);
   }
   if (%IsJSProxy(obj)) {
     return false;
@@ -1249,7 +1159,7 @@
 // ES5 section 15.2.3.13
 function ObjectIsExtensible(obj) {
   if (!IS_SPEC_OBJECT(obj)) {
-    throw MakeTypeError("called_on_non_object", ["Object.isExtensible"]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["isExtensible"]);
   }
   if (%IsJSProxy(obj)) {
     return true;
@@ -1258,16 +1168,6 @@
 }
 
 
-// Harmony egal.
-function ObjectIs(obj1, obj2) {
-  if (obj1 === obj2) {
-    return (obj1 !== 0) || (1 / obj1 === 1 / obj2);
-  } else {
-    return (obj1 !== obj1) && (obj2 !== obj2);
-  }
-}
-
-
 %SetCode($Object, function(x) {
   if (%_IsConstructCall()) {
     if (x == null) return this;
@@ -1307,7 +1207,6 @@
     "getPrototypeOf", ObjectGetPrototypeOf,
     "getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
     "getOwnPropertyNames", ObjectGetOwnPropertyNames,
-    "is", ObjectIs,
     "isExtensible", ObjectIsExtensible,
     "isFrozen", ObjectIsFrozen,
     "isSealed", ObjectIsSealed,
@@ -1338,9 +1237,8 @@
 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) && !IS_BOOLEAN_WRAPPER(this)) {
+  if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
     throw new $TypeError('Boolean.prototype.valueOf is not generic');
-  }
   return %_ValueOf(this);
 }
 
@@ -1380,9 +1278,8 @@
   // 'this'. This is not as dictated by ECMA-262.
   var number = this;
   if (!IS_NUMBER(this)) {
-    if (!IS_NUMBER_WRAPPER(this)) {
+    if (!IS_NUMBER_WRAPPER(this))
       throw new $TypeError('Number.prototype.toString is not generic');
-    }
     // Get the value of this number in case it's an object.
     number = %_ValueOf(this);
   }
@@ -1415,9 +1312,8 @@
 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) && !IS_NUMBER_WRAPPER(this)) {
+  if (!IS_NUMBER(this) && !IS_NUMBER_WRAPPER(this))
     throw new $TypeError('Number.prototype.valueOf is not generic');
-  }
   return %_ValueOf(this);
 }
 
@@ -1443,8 +1339,7 @@
   if (!IS_UNDEFINED(fractionDigits)) {
     f = TO_INTEGER(fractionDigits);
     if (f < 0 || f > 20) {
-      throw new $RangeError(
-          "toExponential() argument must be between 0 and 20");
+      throw new $RangeError("toExponential() argument must be between 0 and 20");
     }
   }
   if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
@@ -1472,18 +1367,6 @@
 }
 
 
-// Harmony isFinite.
-function NumberIsFinite(number) {
-  return IS_NUMBER(number) && NUMBER_IS_FINITE(number);
-}
-
-
-// Harmony isNaN.
-function NumberIsNaN(number) {
-  return IS_NUMBER(number) && NUMBER_IS_NAN(number);
-}
-
-
 // ----------------------------------------------------------------------------
 
 function SetUpNumber() {
@@ -1500,8 +1383,7 @@
                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);
+  %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);
@@ -1528,10 +1410,6 @@
     "toExponential", NumberToExponential,
     "toPrecision", NumberToPrecision
   ));
-  InstallFunctions($Number, DONT_ENUM, $Array(
-    "isFinite", NumberIsFinite,
-    "isNaN", NumberIsNaN
-  ));
 }
 
 SetUpNumber();
@@ -1577,54 +1455,53 @@
 // ES5 15.3.4.5
 function FunctionBind(this_arg) { // Length is 1.
   if (!IS_SPEC_FUNCTION(this)) {
-    throw new $TypeError('Bind must be called on a function');
+      throw new $TypeError('Bind must be called on a function');
   }
-  var boundFunction = function () {
-    // Poison .arguments and .caller, but is otherwise not detectable.
-    "use strict";
-    // This function must not use any object literals (Object, Array, RegExp),
-    // since the literals-array is being used to store the bound data.
-    if (%_IsConstructCall()) {
-      return %NewObjectFromBound(boundFunction);
-    }
-    var bindings = %BoundFunctionGetBindings(boundFunction);
+  // this_arg is not an argument that should be bound.
+  var argc_bound = (%_ArgumentsLength() || 1) - 1;
+  var fn = this;
 
-    var argc = %_ArgumentsLength();
-    if (argc == 0) {
-      return %Apply(bindings[0], bindings[1], bindings, 2, bindings.length - 2);
+  if (argc_bound == 0) {
+    var result = function() {
+      if (%_IsConstructCall()) {
+        // %NewObjectFromBound implicitly uses arguments passed to this
+        // function. We do not pass the arguments object explicitly to avoid
+        // materializing it and guarantee that this function will be optimized.
+        return %NewObjectFromBound(fn, null);
+      }
+      return %Apply(fn, this_arg, arguments, 0, %_ArgumentsLength());
+    };
+  } else {
+    var bound_args = new InternalArray(argc_bound);
+    for(var i = 0; i < argc_bound; i++) {
+      bound_args[i] = %_Arguments(i+1);
     }
-    if (bindings.length === 2) {
-      return %Apply(bindings[0], bindings[1], arguments, 0, argc);
-    }
-    var bound_argc = bindings.length - 2;
-    var argv = new InternalArray(bound_argc + argc);
-    for (var i = 0; i < bound_argc; i++) {
-      argv[i] = bindings[i + 2];
-    }
-    for (var j = 0; j < argc; j++) {
-      argv[i++] = %_Arguments(j);
-    }
-    return %Apply(bindings[0], bindings[1], argv, 0, bound_argc + argc);
-  };
 
-  %FunctionRemovePrototype(boundFunction);
-  var new_length = 0;
-  if (%_ClassOf(this) == "Function") {
-    // Function or FunctionProxy.
-    var old_length = this.length;
-    // FunctionProxies might provide a non-UInt32 value. If so, ignore it.
-    if ((typeof old_length === "number") &&
-        ((old_length >>> 0) === old_length)) {
+    var result = function() {
+      // If this is a construct call we use a special runtime method
+      // to generate the actual object using the bound function.
+      if (%_IsConstructCall()) {
+        // %NewObjectFromBound implicitly uses arguments passed to this
+        // function. We do not pass the arguments object explicitly to avoid
+        // materializing it and guarantee that this function will be optimized.
+        return %NewObjectFromBound(fn, bound_args);
+      }
+
+      // Combine the args we got from the bind call with the args
+      // given as argument to the invocation.
       var argc = %_ArgumentsLength();
-      if (argc > 0) argc--;  // Don't count the thisArg as parameter.
-      new_length = old_length - argc;
-      if (new_length < 0) new_length = 0;
-    }
+      var args = new InternalArray(argc + argc_bound);
+      // Add bound arguments.
+      for (var i = 0; i < argc_bound; i++) {
+        args[i] = bound_args[i];
+      }
+      // Add arguments from call.
+      for (var i = 0; i < argc; i++) {
+        args[argc_bound + i] = %_Arguments(i);
+      }
+      return %Apply(fn, this_arg, args, 0, argc + argc_bound);
+    };
   }
-  // This runtime function finds any remaining arguments on the stack,
-  // so we don't pass the arguments object.
-  var result = %FunctionBindArguments(boundFunction, this,
-                                      this_arg, new_length);
 
   // We already have caller and arguments properties on functions,
   // which are non-configurable. It therefore makes no sence to
@@ -1632,7 +1509,17 @@
   // that bind should make these throw a TypeError if get or set
   // is called and make them non-enumerable and non-configurable.
   // To be consistent with our normal functions we leave this as it is.
-  // TODO(lrn): Do set these to be thrower.
+
+  %FunctionRemovePrototype(result);
+  %FunctionSetBound(result);
+  // Set the correct length. If this is a function proxy, this.length might
+  // throw, or return a bogus result. Leave length alone in that case.
+  // TODO(rossberg): This is underspecified in the current proxy proposal.
+  try {
+    var old_length = ToInteger(this.length);
+    var length = (old_length - argc_bound) > 0 ? old_length - argc_bound : 0;
+    %BoundFunctionSetLength(result, length);
+  } catch(x) {}
   return result;
 }