Push version 1.3.9 to trunk.

Optimized stack guard checks on ARM.

Optimized API operations by inlining more in the API.

Optimized creation of objects from simple constructor functions.

Enabled a number of missing optimizations in the 64-bit port.

Implemented native-code support for regular expressions on ARM.

Stopped using the 'sahf' instruction on 64-bit machines that do not support it.

Fixed a bug in the support for forceful termination of JavaScript execution.



git-svn-id: http://v8.googlecode.com/svn/trunk@2811 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/include/v8.h b/include/v8.h
index a40c068..346050d 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -127,6 +127,12 @@
 class ObjectTemplate;
 class Data;
 
+namespace internal {
+
+class Object;
+
+}
+
 
 // --- W e a k  H a n d l e s
 
@@ -227,8 +233,8 @@
    * The handles' references are not checked.
    */
   template <class S> bool operator==(Handle<S> that) const {
-    void** a = reinterpret_cast<void**>(**this);
-    void** b = reinterpret_cast<void**>(*that);
+    internal::Object** a = reinterpret_cast<internal::Object**>(**this);
+    internal::Object** b = reinterpret_cast<internal::Object**>(*that);
     if (a == 0) return b == 0;
     if (b == 0) return false;
     return *a == *b;
@@ -245,7 +251,11 @@
   }
 
   template <class S> static inline Handle<T> Cast(Handle<S> that) {
+#ifdef V8_ENABLE_CHECKS
+    // If we're going to perform the type check then we have to check
+    // that the handle isn't empty before doing the checked cast.
     if (that.IsEmpty()) return Handle<T>();
+#endif
     return Handle<T>(T::Cast(*that));
   }
 
@@ -275,7 +285,11 @@
   }
   template <class S> inline Local(S* that) : Handle<T>(that) { }
   template <class S> static inline Local<T> Cast(Local<S> that) {
+#ifdef V8_ENABLE_CHECKS
+    // If we're going to perform the type check then we have to check
+    // that the handle isn't empty before doing the checked cast.
     if (that.IsEmpty()) return Local<T>();
+#endif
     return Local<T>(T::Cast(*that));
   }
 
@@ -344,7 +358,11 @@
       : Handle<T>(*that) { }
 
   template <class S> static inline Persistent<T> Cast(Persistent<S> that) {
+#ifdef V8_ENABLE_CHECKS
+    // If we're going to perform the type check then we have to check
+    // that the handle isn't empty before doing the checked cast.
     if (that.IsEmpty()) return Persistent<T>();
+#endif
     return Persistent<T>(T::Cast(*that));
   }
 
@@ -423,7 +441,7 @@
   /**
    * Creates a new handle with the given value.
    */
-  static void** CreateHandle(void* value);
+  static internal::Object** CreateHandle(internal::Object* value);
 
  private:
   // Make it impossible to create heap-allocated or illegal handle
@@ -438,8 +456,8 @@
   class V8EXPORT Data {
    public:
     int extensions;
-    void** next;
-    void** limit;
+    internal::Object** next;
+    internal::Object** limit;
     inline void Initialize() {
       extensions = -1;
       next = limit = NULL;
@@ -451,7 +469,7 @@
   // Allow for the active closing of HandleScopes which allows to pass a handle
   // from the HandleScope being closed to the next top most HandleScope.
   bool is_closed_;
-  void** RawClose(void** value);
+  internal::Object** RawClose(internal::Object** value);
 
   friend class ImplementationUtilities;
 };
@@ -671,7 +689,7 @@
    * Returns true if this value is an instance of the String type.
    * See ECMA-262 8.4.
    */
-  bool IsString() const;
+  inline bool IsString() const;
 
   /**
    * Returns true if this value is a function.
@@ -737,6 +755,10 @@
   /** JS == */
   bool Equals(Handle<Value> that) const;
   bool StrictEquals(Handle<Value> that) const;
+  
+ private:
+  inline bool QuickIsString() const;
+  bool FullIsString() const;
 };
 
 
@@ -868,7 +890,7 @@
    * Get the ExternalStringResource for an external string.  Returns
    * NULL if IsExternal() doesn't return true.
    */
-  ExternalStringResource* GetExternalStringResource() const;
+  inline ExternalStringResource* GetExternalStringResource() const;
 
   /**
    * Get the ExternalAsciiStringResource for an external ascii string.
@@ -876,7 +898,7 @@
    */
   ExternalAsciiStringResource* GetExternalAsciiStringResource() const;
 
-  static String* Cast(v8::Value* obj);
+  static inline String* Cast(v8::Value* obj);
 
   /**
    * Allocates a new string from either utf-8 encoded or ascii data.
@@ -1010,6 +1032,10 @@
     Value(const Value&);
     void operator=(const Value&);
   };
+  
+ private:
+  void VerifyExternalStringResource(ExternalStringResource* val) const;
+  static void CheckCast(v8::Value* obj);
 };
 
 
@@ -1020,9 +1046,10 @@
  public:
   double Value() const;
   static Local<Number> New(double value);
-  static Number* Cast(v8::Value* obj);
+  static inline Number* Cast(v8::Value* obj);
  private:
   Number();
+  static void CheckCast(v8::Value* obj);
 };
 
 
@@ -1033,9 +1060,10 @@
  public:
   static Local<Integer> New(int32_t value);
   int64_t Value() const;
-  static Integer* Cast(v8::Value* obj);
+  static inline Integer* Cast(v8::Value* obj);
  private:
   Integer();
+  static void CheckCast(v8::Value* obj);
 };
 
 
@@ -1074,7 +1102,9 @@
    */
   double NumberValue() const;
 
-  static Date* Cast(v8::Value* obj);
+  static inline Date* Cast(v8::Value* obj);
+ private:
+  static void CheckCast(v8::Value* obj);
 };
 
 
@@ -1153,14 +1183,13 @@
   /** Gets the number of internal fields for this Object. */
   int InternalFieldCount();
   /** Gets the value in an internal field. */
-  Local<Value> GetInternalField(int index);
+  inline Local<Value> GetInternalField(int index);
   /** Sets the value in an internal field. */
   void SetInternalField(int index, Handle<Value> value);
 
-  // The two functions below do not perform index bounds checks and
-  // they do not check that the VM is still running. Use with caution.
   /** Gets a native pointer from an internal field. */
-  void* GetPointerFromInternalField(int index);
+  inline void* GetPointerFromInternalField(int index);
+  
   /** Sets a native pointer in an internal field. */
   void SetPointerInInternalField(int index, void* value);
 
@@ -1223,9 +1252,17 @@
   void SetIndexedPropertiesToPixelData(uint8_t* data, int length);
 
   static Local<Object> New();
-  static Object* Cast(Value* obj);
+  static inline Object* Cast(Value* obj);
  private:
   Object();
+  static void CheckCast(Value* obj);
+  Local<Value> CheckedGetInternalField(int index);
+
+  /**
+   * If quick access to the internal field is possible this method
+   * returns the value.  Otherwise an empty handle is returned. 
+   */
+  inline Local<Value> UncheckedGetInternalField(int index);
 };
 
 
@@ -1243,9 +1280,10 @@
   Local<Object> CloneElementAt(uint32_t index);
 
   static Local<Array> New(int length = 0);
-  static Array* Cast(Value* obj);
+  static inline Array* Cast(Value* obj);
  private:
   Array();
+  static void CheckCast(Value* obj);
 };
 
 
@@ -1259,9 +1297,10 @@
   Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]);
   void SetName(Handle<String> name);
   Handle<Value> GetName() const;
-  static Function* Cast(Value* obj);
+  static inline Function* Cast(Value* obj);
  private:
   Function();
+  static void CheckCast(Value* obj);
 };
 
 
@@ -1279,13 +1318,16 @@
 class V8EXPORT External : public Value {
  public:
   static Local<Value> Wrap(void* data);
-  static void* Unwrap(Handle<Value> obj);
+  static inline void* Unwrap(Handle<Value> obj);
 
   static Local<External> New(void* value);
-  static External* Cast(Value* obj);
+  static inline External* Cast(Value* obj);
   void* Value() const;
  private:
   External();
+  static void CheckCast(v8::Value* obj);
+  static inline void* QuickUnwrap(Handle<v8::Value> obj);
+  static void* FullUnwrap(Handle<v8::Value> obj);
 };
 
 
@@ -2297,12 +2339,14 @@
  private:
   V8();
 
-  static void** GlobalizeReference(void** handle);
-  static void DisposeGlobal(void** global_handle);
-  static void MakeWeak(void** global_handle, void* data, WeakReferenceCallback);
-  static void ClearWeak(void** global_handle);
-  static bool IsGlobalNearDeath(void** global_handle);
-  static bool IsGlobalWeak(void** global_handle);
+  static internal::Object** GlobalizeReference(internal::Object** handle);
+  static void DisposeGlobal(internal::Object** global_handle);
+  static void MakeWeak(internal::Object** global_handle,
+                       void* data,
+                       WeakReferenceCallback);
+  static void ClearWeak(internal::Object** global_handle);
+  static bool IsGlobalNearDeath(internal::Object** global_handle);
+  static bool IsGlobalWeak(internal::Object** global_handle);
 
   template <class T> friend class Handle;
   template <class T> friend class Local;
@@ -2641,6 +2685,76 @@
 
 // --- I m p l e m e n t a t i o n ---
 
+
+namespace internal {
+
+
+// Tag information for HeapObject.
+const int kHeapObjectTag = 1;
+const int kHeapObjectTagSize = 2;
+const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
+
+
+// Tag information for Smi.
+const int kSmiTag = 0;
+const int kSmiTagSize = 1;
+const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
+
+
+/**
+ * This class exports constants and functionality from within v8 that
+ * is necessary to implement inline functions in the v8 api.  Don't
+ * depend on functions and constants defined here.
+ */
+class Internals {
+ public:
+
+  // These values match non-compiler-dependent values defined within
+  // the implementation of v8.
+  static const int kHeapObjectMapOffset = 0;
+  static const int kMapInstanceTypeOffset = sizeof(void*) + sizeof(int);
+  static const int kStringResourceOffset = 2 * sizeof(void*);
+  static const int kProxyProxyOffset = sizeof(void*);
+  static const int kJSObjectHeaderSize = 3 * sizeof(void*);
+  static const int kFullStringRepresentationMask = 0x07;
+  static const int kExternalTwoByteRepresentationTag = 0x03;
+  static const int kAlignedPointerShift = 2;
+
+  // These constants are compiler dependent so their values must be
+  // defined within the implementation.
+  static int kJSObjectType;
+  static int kFirstNonstringType;
+  static int kProxyType;
+
+  static inline bool HasHeapObjectTag(internal::Object* value) {
+    return ((reinterpret_cast<intptr_t>(value) & kHeapObjectTagMask) ==
+            kHeapObjectTag);
+  }
+  
+  static inline bool HasSmiTag(internal::Object* value) {
+    return ((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag);
+  }
+  
+  static inline int SmiValue(internal::Object* value) {
+    return static_cast<int>(reinterpret_cast<intptr_t>(value)) >> kSmiTagSize;
+  }
+  
+  static inline bool IsExternalTwoByteString(int instance_type) {
+    int representation = (instance_type & kFullStringRepresentationMask);
+    return representation == kExternalTwoByteRepresentationTag;
+  }
+
+  template <typename T>
+  static inline T ReadField(Object* ptr, int offset) {
+    uint8_t* addr = reinterpret_cast<uint8_t*>(ptr) + offset - kHeapObjectTag;
+    return *reinterpret_cast<T*>(addr);
+  }
+
+};
+
+}
+
+
 template <class T>
 Handle<T>::Handle() : val_(0) { }
 
@@ -2652,7 +2766,7 @@
 template <class T>
 Local<T> Local<T>::New(Handle<T> that) {
   if (that.IsEmpty()) return Local<T>();
-  void** p = reinterpret_cast<void**>(*that);
+  internal::Object** p = reinterpret_cast<internal::Object**>(*that);
   return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(*p)));
 }
 
@@ -2660,7 +2774,7 @@
 template <class T>
 Persistent<T> Persistent<T>::New(Handle<T> that) {
   if (that.IsEmpty()) return Persistent<T>();
-  void** p = reinterpret_cast<void**>(*that);
+  internal::Object** p = reinterpret_cast<internal::Object**>(*that);
   return Persistent<T>(reinterpret_cast<T*>(V8::GlobalizeReference(p)));
 }
 
@@ -2668,21 +2782,21 @@
 template <class T>
 bool Persistent<T>::IsNearDeath() const {
   if (this->IsEmpty()) return false;
-  return V8::IsGlobalNearDeath(reinterpret_cast<void**>(**this));
+  return V8::IsGlobalNearDeath(reinterpret_cast<internal::Object**>(**this));
 }
 
 
 template <class T>
 bool Persistent<T>::IsWeak() const {
   if (this->IsEmpty()) return false;
-  return V8::IsGlobalWeak(reinterpret_cast<void**>(**this));
+  return V8::IsGlobalWeak(reinterpret_cast<internal::Object**>(**this));
 }
 
 
 template <class T>
 void Persistent<T>::Dispose() {
   if (this->IsEmpty()) return;
-  V8::DisposeGlobal(reinterpret_cast<void**>(**this));
+  V8::DisposeGlobal(reinterpret_cast<internal::Object**>(**this));
 }
 
 
@@ -2691,12 +2805,14 @@
 
 template <class T>
 void Persistent<T>::MakeWeak(void* parameters, WeakReferenceCallback callback) {
-  V8::MakeWeak(reinterpret_cast<void**>(**this), parameters, callback);
+  V8::MakeWeak(reinterpret_cast<internal::Object**>(**this),
+               parameters,
+               callback);
 }
 
 template <class T>
 void Persistent<T>::ClearWeak() {
-  V8::ClearWeak(reinterpret_cast<void**>(**this));
+  V8::ClearWeak(reinterpret_cast<internal::Object**>(**this));
 }
 
 Local<Value> Arguments::operator[](int i) const {
@@ -2752,7 +2868,8 @@
 
 template <class T>
 Local<T> HandleScope::Close(Handle<T> value) {
-  void** after = RawClose(reinterpret_cast<void**>(*value));
+  internal::Object** before = reinterpret_cast<internal::Object**>(*value);
+  internal::Object** after = RawClose(before);
   return Local<T>(reinterpret_cast<T*>(after));
 }
 
@@ -2781,6 +2898,171 @@
 }
 
 
+Local<Value> Object::GetInternalField(int index) {
+#ifndef V8_ENABLE_CHECKS
+  Local<Value> quick_result = UncheckedGetInternalField(index);
+  if (!quick_result.IsEmpty()) return quick_result;
+#endif
+  return CheckedGetInternalField(index);
+}
+
+
+Local<Value> Object::UncheckedGetInternalField(int index) {
+  typedef internal::Object O;
+  typedef internal::Internals I;
+  O* obj = *reinterpret_cast<O**>(this);
+  O* map = I::ReadField<O*>(obj, I::kHeapObjectMapOffset);
+  int instance_type = I::ReadField<uint8_t>(map, I::kMapInstanceTypeOffset);
+  if (instance_type == I::kJSObjectType) {
+    // If the object is a plain JSObject, which is the common case,
+    // we know where to find the internal fields and can return the
+    // value directly.
+    int offset = I::kJSObjectHeaderSize + (sizeof(void*) * index);
+    O* value = I::ReadField<O*>(obj, offset);
+    O** result = HandleScope::CreateHandle(value);
+    return Local<Value>(reinterpret_cast<Value*>(result));
+  } else {
+    return Local<Value>();
+  }
+}
+
+
+void* External::Unwrap(Handle<v8::Value> obj) {
+#ifdef V8_ENABLE_CHECKS
+  return FullUnwrap(obj);
+#else
+  return QuickUnwrap(obj);
+#endif
+}
+
+
+void* External::QuickUnwrap(Handle<v8::Value> wrapper) {
+  typedef internal::Object O;
+  typedef internal::Internals I;
+  O* obj = *reinterpret_cast<O**>(const_cast<v8::Value*>(*wrapper));
+  if (I::HasSmiTag(obj)) {
+    int value = I::SmiValue(obj) << I::kAlignedPointerShift;
+    return reinterpret_cast<void*>(value);
+  } else {
+    O* map = I::ReadField<O*>(obj, I::kHeapObjectMapOffset);
+    int instance_type = I::ReadField<uint8_t>(map, I::kMapInstanceTypeOffset);
+    if (instance_type == I::kProxyType) {
+      return I::ReadField<void*>(obj, I::kProxyProxyOffset);
+    } else {
+      return NULL;
+    }
+  }
+}
+
+
+void* Object::GetPointerFromInternalField(int index) {
+  return External::Unwrap(GetInternalField(index));
+}
+
+
+String* String::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<String*>(value);
+}
+
+
+String::ExternalStringResource* String::GetExternalStringResource() const {
+  typedef internal::Object O;
+  typedef internal::Internals I;
+  O* obj = *reinterpret_cast<O**>(const_cast<String*>(this));
+  O* map = I::ReadField<O*>(obj, I::kHeapObjectMapOffset);
+  int instance_type = I::ReadField<uint8_t>(map, I::kMapInstanceTypeOffset);
+  String::ExternalStringResource* result;
+  if (I::IsExternalTwoByteString(instance_type)) {
+    void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
+    result = reinterpret_cast<String::ExternalStringResource*>(value);
+  } else {
+    result = NULL;
+  }
+#ifdef V8_ENABLE_CHECKS
+  VerifyExternalStringResource(result);
+#endif
+  return result;
+}
+
+
+bool Value::IsString() const {
+#ifdef V8_ENABLE_CHECKS
+  return FullIsString();
+#else
+  return QuickIsString();
+#endif
+}
+
+bool Value::QuickIsString() const {
+  typedef internal::Object O;
+  typedef internal::Internals I;
+  O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+  if (!I::HasHeapObjectTag(obj)) return false;
+  O* map = I::ReadField<O*>(obj, I::kHeapObjectMapOffset);
+  int instance_type = I::ReadField<uint8_t>(map, I::kMapInstanceTypeOffset);
+  return (instance_type < I::kFirstNonstringType);
+}
+
+
+Number* Number::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Number*>(value);
+}
+
+
+Integer* Integer::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Integer*>(value);
+}
+
+
+Date* Date::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Date*>(value);
+}
+
+
+Object* Object::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Object*>(value);
+}
+
+
+Array* Array::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Array*>(value);
+}
+
+
+Function* Function::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Function*>(value);
+}
+
+
+External* External::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<External*>(value);
+}
+
+
 /**
  * \example shell.cc
  * A simple shell that takes a list of expressions on the