Heavy cleanup of the external pointer API.
authorsvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 5 Nov 2012 10:25:32 +0000 (10:25 +0000)
committersvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 5 Nov 2012 10:25:32 +0000 (10:25 +0000)
Added highly efficient Object::SetAlignedPointerInInternalField and
Object::GetAlignedPointerFromInternalField functions for 2-byte-aligned
pointers. Their non-aligned counterparts Object::GetPointerFromInternalField and
Object::SetPointerInInternalField are now deprecated utility functions.

External is now a true Value again, with New/Value/Cast using a JSObject with an
internal field containing a Foreign. External::Wrap, and External::Unwrap are now
deprecated utility functions.

Added Context::GetEmbedderData and Context::SetEmbedderData. Deprecated
Context::GetData and Context::SetData, these are now only wrappers to access
internal field 0.

Added highly efficient Context::SetAlignedPointerInEmbedderData and
Context::GetAlignedPointerFromEmbedderData functions for 2-byte-aligned
pointers.

Review URL: https://codereview.chromium.org/11190050

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12849 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

17 files changed:
include/v8.h
src/api.cc
src/api.h
src/bootstrapper.cc
src/compiler.cc
src/contexts.h
src/factory.cc
src/factory.h
src/heap.cc
src/heap.h
src/objects-inl.h
src/objects.h
src/profile-generator.cc
test/cctest/test-api.cc
test/cctest/test-debug.cc
test/cctest/test-decls.cc
tools/grokdump.py

index 65d302e7bd1f0fa607c551a41b4d3b7d664a52a1..811f8ffd26128c85ba0b537792eae0cbc0c98315 100644 (file)
 
 #endif  // _WIN32
 
+// TODO(svenpanne) Remove this when the Chrome's v8 bindings have been adapted.
+#define V8_DISABLE_DEPRECATIONS 1
+
+#if defined(__GNUC__) && !defined(V8_DISABLE_DEPRECATIONS)
+#define V8_DEPRECATED(func) func __attribute__ ((deprecated))
+#elif defined(_MSC_VER) && !defined(V8_DISABLE_DEPRECATIONS)
+#define V8_DEPRECATED(func) __declspec(deprecated) func
+#else
+#define V8_DEPRECATED(func) func
+#endif
+
 /**
  * The v8 JavaScript engine.
  */
@@ -1587,16 +1598,41 @@ class Object : public Value {
 
   /** Gets the number of internal fields for this Object. */
   V8EXPORT int InternalFieldCount();
-  /** Gets the value in an internal field. */
+
+  /** Gets the value from an internal field. */
   inline Local<Value> GetInternalField(int index);
+
   /** Sets the value in an internal field. */
   V8EXPORT void SetInternalField(int index, Handle<Value> value);
 
-  /** Gets a native pointer from an internal field. */
-  inline void* GetPointerFromInternalField(int index);
+  /**
+   * Gets a native pointer from an internal field. Deprecated. If the pointer is
+   * always 2-byte-aligned, use GetAlignedPointerFromInternalField instead,
+   * otherwise use a combination of GetInternalField, External::Cast and
+   * External::Value.
+   */
+  V8_DEPRECATED(void* GetPointerFromInternalField(int index));
+
+  /**
+   * Sets a native pointer in an internal field. Deprecated. If the pointer is
+   * always 2-byte aligned, use SetAlignedPointerInInternalField instead,
+   * otherwise use a combination of External::New and SetInternalField.
+   */
+  inline V8_DEPRECATED(void SetPointerInInternalField(int index, void* value));
 
-  /** Sets a native pointer in an internal field. */
-  V8EXPORT void SetPointerInInternalField(int index, void* value);
+  /**
+   * Gets a 2-byte-aligned native pointer from an internal field. This field
+   * must have been set by SetAlignedPointerInInternalField, everything else
+   * leads to undefined behavior.
+   */
+  inline void* GetAlignedPointerFromInternalField(int index);
+
+  /**
+   * Sets a 2-byte-aligned native pointer in an internal field. To retrieve such
+   * a field, GetAlignedPointerFromInternalField must be used, everything else
+   * leads to undefined behavior.
+   */
+  V8EXPORT void SetAlignedPointerInInternalField(int index, void* value);
 
   // Testers for local properties.
   V8EXPORT bool HasOwnProperty(Handle<String> key);
@@ -1727,14 +1763,8 @@ class Object : public Value {
  private:
   V8EXPORT Object();
   V8EXPORT static void CheckCast(Value* obj);
-  V8EXPORT Local<Value> CheckedGetInternalField(int index);
-  V8EXPORT void* SlowGetPointerFromInternalField(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);
+  V8EXPORT Local<Value> SlowGetInternalField(int index);
+  V8EXPORT void* SlowGetAlignedPointerFromInternalField(int index);
 };
 
 
@@ -1945,29 +1975,22 @@ class RegExp : public Object {
 
 
 /**
- * A JavaScript value that wraps a C++ void*.  This type of value is
- * mainly used to associate C++ data structures with JavaScript
- * objects.
- *
- * The Wrap function V8 will return the most optimal Value object wrapping the
- * C++ void*. The type of the value is not guaranteed to be an External object
- * and no assumptions about its type should be made. To access the wrapped
- * value Unwrap should be used, all other operations on that object will lead
- * to unpredictable results.
+ * A JavaScript value that wraps a C++ void*. This type of value is mainly used
+ * to associate C++ data structures with JavaScript objects.
  */
 class External : public Value {
  public:
-  V8EXPORT static Local<Value> Wrap(void* data);
-  static inline void* Unwrap(Handle<Value> obj);
+  /** Deprecated, use New instead. */
+  V8_DEPRECATED(static inline Local<Value> Wrap(void* value));
+
+  /** Deprecated, use a combination of Cast and Value instead. */
+  V8_DEPRECATED(static inline void* Unwrap(Handle<Value> obj));
 
   V8EXPORT static Local<External> New(void* value);
   static inline External* Cast(Value* obj);
   V8EXPORT void* Value() const;
  private:
-  V8EXPORT External();
   V8EXPORT static void CheckCast(v8::Value* obj);
-  static inline void* QuickUnwrap(Handle<v8::Value> obj);
-  V8EXPORT static void* FullUnwrap(Handle<v8::Value> obj);
 };
 
 
@@ -3744,12 +3767,45 @@ class V8EXPORT Context {
   static bool InContext();
 
   /**
-   * Associate an additional data object with the context. This is mainly used
-   * with the debugger to provide additional information on the context through
-   * the debugger API.
+   * Gets embedder data with index 0. Deprecated, use GetEmbedderData with index
+   * 0 instead.
+   */
+  V8_DEPRECATED(inline Local<Value> GetData());
+
+  /**
+   * Sets embedder data with index 0. Deprecated, use SetEmbedderData with index
+   * 0 instead.
    */
-  void SetData(Handle<Value> data);
-  Local<Value> GetData();
+  V8_DEPRECATED(inline void SetData(Handle<Value> value));
+
+  /**
+   * Gets the embedder data with the given index, which must have been set by a
+   * previous call to SetEmbedderData with the same index. Note that index 0
+   * currently has a special meaning for Chrome's debugger.
+   */
+  inline Local<Value> GetEmbedderData(int index);
+
+  /**
+   * Sets the embedder data with the given index, growing the data as
+   * needed. Note that index 0 currently has a special meaning for Chrome's
+   * debugger.
+   */
+  void SetEmbedderData(int index, Handle<Value> value);
+
+  /**
+   * Gets a 2-byte-aligned native pointer from the embedder data with the given
+   * index, which must have bees set by a previous call to
+   * SetAlignedPointerInEmbedderData with the same index. Note that index 0
+   * currently has a special meaning for Chrome's debugger.
+   */
+  inline void* GetAlignedPointerFromEmbedderData(int index);
+
+  /**
+   * Sets a 2-byte-aligned native pointer in the embedder data with the given
+   * index, growing the data as needed. Note that index 0 currently has a
+   * special meaning for Chrome's debugger.
+   */
+  void SetAlignedPointerInEmbedderData(int index, void* value);
 
   /**
    * Control whether code generation from strings is allowed. Calling
@@ -3798,6 +3854,9 @@ class V8EXPORT Context {
   friend class Script;
   friend class Object;
   friend class Function;
+
+  Local<Value> SlowGetEmbedderData(int index);
+  void* SlowGetAlignedPointerFromEmbedderData(int index);
 };
 
 
@@ -4031,11 +4090,6 @@ template <> struct SmiTagging<4> {
     // Throw away top 32 bits and shift down (requires >> to be sign extending).
     return static_cast<int>(reinterpret_cast<intptr_t>(value)) >> shift_bits;
   }
-
-  // For 32-bit systems any 2 bytes aligned pointer can be encoded as smi
-  // with a plain reinterpret_cast.
-  static const uintptr_t kEncodablePointerMask = 0x1;
-  static const int kPointerToSmiShift = 0;
 };
 
 // Smi constants for 64-bit systems.
@@ -4047,26 +4101,11 @@ template <> struct SmiTagging<8> {
     // Shift down and throw away top 32 bits.
     return static_cast<int>(reinterpret_cast<intptr_t>(value) >> shift_bits);
   }
-
-  // To maximize the range of pointers that can be encoded
-  // in the available 32 bits, we require them to be 8 bytes aligned.
-  // This gives 2 ^ (32 + 3) = 32G address space covered.
-  // It might be not enough to cover stack allocated objects on some platforms.
-  static const int kPointerAlignment = 3;
-
-  static const uintptr_t kEncodablePointerMask =
-      ~(uintptr_t(0xffffffff) << kPointerAlignment);
-
-  static const int kPointerToSmiShift =
-      kSmiTagSize + kSmiShiftSize - kPointerAlignment;
 };
 
 typedef SmiTagging<kApiPointerSize> PlatformSmiTagging;
 const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
 const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
-const uintptr_t kEncodablePointerMask =
-    PlatformSmiTagging::kEncodablePointerMask;
-const int kPointerToSmiShift = PlatformSmiTagging::kPointerToSmiShift;
 
 /**
  * This class exports constants and functionality from within v8 that
@@ -4084,6 +4123,9 @@ class Internals {
   static const int kOddballKindOffset = 3 * kApiPointerSize;
   static const int kForeignAddressOffset = kApiPointerSize;
   static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
+  static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
+  static const int kContextHeaderSize = 2 * kApiPointerSize;
+  static const int kContextEmbedderDataIndex = 54;
   static const int kFullStringRepresentationMask = 0x07;
   static const int kStringEncodingMask = 0x4;
   static const int kExternalTwoByteRepresentationTag = 0x02;
@@ -4096,7 +4138,7 @@ class Internals {
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptySymbolRootIndex = 117;
+  static const int kEmptySymbolRootIndex = 118;
 
   static const int kJSObjectType = 0xaa;
   static const int kFirstNonstringType = 0x80;
@@ -4111,10 +4153,6 @@ class Internals {
             kHeapObjectTag);
   }
 
-  static inline bool HasSmiTag(internal::Object* value) {
-    return ((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag);
-  }
-
   static inline int SmiValue(internal::Object* value) {
     return PlatformSmiTagging::SmiToInt(value);
   }
@@ -4130,21 +4168,6 @@ class Internals {
     return SmiValue(ReadField<O*>(obj, kOddballKindOffset));
   }
 
-  static inline void* GetExternalPointerFromSmi(internal::Object* value) {
-    const uintptr_t address = reinterpret_cast<uintptr_t>(value);
-    return reinterpret_cast<void*>(address >> kPointerToSmiShift);
-  }
-
-  static inline void* GetExternalPointer(internal::Object* obj) {
-    if (HasSmiTag(obj)) {
-      return GetExternalPointerFromSmi(obj);
-    } else if (GetInstanceType(obj) == kForeignType) {
-      return ReadField<void*>(obj, kForeignAddressOffset);
-    } else {
-      return NULL;
-    }
-  }
-
   static inline bool IsExternalTwoByteString(int instance_type) {
     int representation = (instance_type & kFullStringRepresentationMask);
     return representation == kExternalTwoByteRepresentationTag;
@@ -4178,6 +4201,19 @@ class Internals {
     return *reinterpret_cast<T*>(addr);
   }
 
+  template <typename T>
+  static inline T ReadEmbedderData(Context* context, int index) {
+    typedef internal::Object O;
+    typedef internal::Internals I;
+    O* ctx = *reinterpret_cast<O**>(context);
+    int embedder_data_offset = I::kContextHeaderSize +
+        (internal::kApiPointerSize * I::kContextEmbedderDataIndex);
+    O* embedder_data = I::ReadField<O*>(ctx, embedder_data_offset);
+    int value_offset =
+        I::kFixedArrayHeaderSize + (internal::kApiPointerSize * index);
+    return I::ReadField<T>(embedder_data, value_offset);
+  }
+
   static inline bool CanCastToHeapObject(void* o) { return false; }
   static inline bool CanCastToHeapObject(Context* o) { return true; }
   static inline bool CanCastToHeapObject(String* o) { return true; }
@@ -4359,63 +4395,40 @@ void Template::Set(const char* name, v8::Handle<Data> value) {
 
 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);
+  // Fast path: 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.
   if (I::GetInstanceType(obj) == 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 + (internal::kApiPointerSize * 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
+  return SlowGetInternalField(index);
 }
 
 
-void* External::QuickUnwrap(Handle<v8::Value> wrapper) {
-  typedef internal::Object O;
-  O* obj = *reinterpret_cast<O**>(const_cast<v8::Value*>(*wrapper));
-  return internal::Internals::GetExternalPointer(obj);
+void Object::SetPointerInInternalField(int index, void* value) {
+  SetInternalField(index, External::New(value));
 }
 
 
-void* Object::GetPointerFromInternalField(int index) {
+void* Object::GetAlignedPointerFromInternalField(int index) {
+#ifndef V8_ENABLE_CHECKS
   typedef internal::Object O;
   typedef internal::Internals I;
-
   O* obj = *reinterpret_cast<O**>(this);
-
+  // Fast path: 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.
   if (I::GetInstanceType(obj) == 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 + (internal::kApiPointerSize * index);
-    O* value = I::ReadField<O*>(obj, offset);
-    return I::GetExternalPointer(value);
+    return I::ReadField<void*>(obj, offset);
   }
-
-  return SlowGetPointerFromInternalField(index);
+#endif
+  return SlowGetAlignedPointerFromInternalField(index);
 }
 
 
@@ -4607,6 +4620,16 @@ Function* Function::Cast(v8::Value* value) {
 }
 
 
+Local<Value> External::Wrap(void* value) {
+  return External::New(value);
+}
+
+
+void* External::Unwrap(Handle<v8::Value> obj) {
+  return External::Cast(*obj)->Value();
+}
+
+
 External* External::Cast(v8::Value* value) {
 #ifdef V8_ENABLE_CHECKS
   CheckCast(value);
@@ -4683,6 +4706,37 @@ void* Isolate::GetData() {
 }
 
 
+Local<Value> Context::GetData() {
+  return GetEmbedderData(0);
+}
+
+void Context::SetData(Handle<Value> data) {
+  SetEmbedderData(0, data);
+}
+
+
+Local<Value> Context::GetEmbedderData(int index) {
+#ifndef V8_ENABLE_CHECKS
+  typedef internal::Object O;
+  typedef internal::Internals I;
+  O** result = HandleScope::CreateHandle(I::ReadEmbedderData<O*>(this, index));
+  return Local<Value>(reinterpret_cast<Value*>(result));
+#else
+  return SlowGetEmbedderData(index);
+#endif
+}
+
+
+void* Context::GetAlignedPointerFromEmbedderData(int index) {
+#ifndef V8_ENABLE_CHECKS
+  typedef internal::Internals I;
+  return I::ReadEmbedderData<void*>(this, index);
+#else
+  return SlowGetAlignedPointerFromEmbedderData(index);
+#endif
+}
+
+
 /**
  * \example shell.cc
  * A simple shell that takes a list of expressions on the
index be7d73f50906edcf0343d326e592520b71195285..1c15134f42934a54089562d6c10d784f6892080a 100644 (file)
@@ -25,6 +25,9 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Deprecated API entries use other deprecated entries, too.
+#define V8_DISABLE_DEPRECATIONS 1
+
 #include "api.h"
 
 #include <math.h>  // For isnan.
@@ -773,33 +776,77 @@ void Context::Exit() {
 }
 
 
-void Context::SetData(v8::Handle<Value> data) {
-  i::Handle<i::Context> env = Utils::OpenHandle(this);
-  i::Isolate* isolate = env->GetIsolate();
-  if (IsDeadCheck(isolate, "v8::Context::SetData()")) return;
-  i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
-  ASSERT(env->IsNativeContext());
-  if (env->IsNativeContext()) {
-    env->set_data(*raw_data);
-  }
+static void* DecodeSmiToAligned(i::Object* value, const char* location) {
+  ApiCheck(value->IsSmi(), location, "Not a Smi");
+  return reinterpret_cast<void*>(value);
 }
 
 
-v8::Local<v8::Value> Context::GetData() {
-  i::Handle<i::Context> env = Utils::OpenHandle(this);
-  i::Isolate* isolate = env->GetIsolate();
-  if (IsDeadCheck(isolate, "v8::Context::GetData()")) {
-    return Local<Value>();
-  }
-  ASSERT(env->IsNativeContext());
-  if (!env->IsNativeContext()) {
-    return Local<Value>();
+static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
+  i::Smi* smi = reinterpret_cast<i::Smi*>(value);
+  ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
+  return smi;
+}
+
+
+static i::Handle<i::FixedArray> EmbedderDataFor(Context* context,
+                                                int index,
+                                                bool can_grow,
+                                                const char* location) {
+  i::Handle<i::Context> env = Utils::OpenHandle(context);
+  bool ok = !IsDeadCheck(env->GetIsolate(), location) &&
+      ApiCheck(env->IsNativeContext(), location, "Not a native context") &&
+      ApiCheck(index >= 0, location, "Negative index");
+  if (!ok) return i::Handle<i::FixedArray>();
+  i::Handle<i::FixedArray> data(env->embedder_data());
+  if (index < data->length()) return data;
+  if (!can_grow) {
+    Utils::ReportApiFailure(location, "Index too large");
+    return i::Handle<i::FixedArray>();
   }
-  i::Handle<i::Object> result(env->data(), isolate);
+  int new_size = i::Max(index, data->length() << 1) + 1;
+  data = env->GetIsolate()->factory()->CopySizeFixedArray(data, new_size);
+  env->set_embedder_data(*data);
+  return data;
+}
+
+
+v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
+  const char* location = "v8::Context::GetEmbedderData()";
+  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
+  if (data.is_null()) return Local<Value>();
+  i::Handle<i::Object> result(data->get(index), data->GetIsolate());
   return Utils::ToLocal(result);
 }
 
 
+void Context::SetEmbedderData(int index, v8::Handle<Value> value) {
+  const char* location = "v8::Context::SetEmbedderData()";
+  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
+  if (data.is_null()) return;
+  i::Handle<i::Object> val = Utils::OpenHandle(*value);
+  data->set(index, *val);
+  ASSERT_EQ(*Utils::OpenHandle(*value),
+            *Utils::OpenHandle(*GetEmbedderData(index)));
+}
+
+
+void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
+  const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
+  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
+  if (data.is_null()) return NULL;
+  return DecodeSmiToAligned(data->get(index), location);
+}
+
+
+void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
+  const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
+  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
+  data->set(index, EncodeAlignedAsSmi(value, location));
+  ASSERT_EQ(value, GetAlignedPointerFromEmbedderData(index));
+}
+
+
 i::Object** v8::HandleScope::RawClose(i::Object** value) {
   if (!ApiCheck(!is_closed_,
                 "v8::HandleScope::Close()",
@@ -2198,7 +2245,7 @@ bool Value::IsExternal() const {
   if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsExternal()")) {
     return false;
   }
-  return Utils::OpenHandle(this)->IsForeign();
+  return Utils::OpenHandle(this)->IsExternal();
 }
 
 
@@ -2427,8 +2474,7 @@ Local<Integer> Value::ToInteger() const {
 
 void External::CheckCast(v8::Value* that) {
   if (IsDeadCheck(i::Isolate::Current(), "v8::External::Cast()")) return;
-  i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->IsForeign(),
+  ApiCheck(Utils::OpenHandle(that)->IsExternal(),
            "v8::External::Cast()",
            "Could not convert to external");
 }
@@ -4191,75 +4237,65 @@ int v8::Object::InternalFieldCount() {
 }
 
 
-Local<Value> v8::Object::CheckedGetInternalField(int index) {
+static bool InternalFieldOK(i::Handle<i::JSObject> obj,
+                            int index,
+                            const char* location) {
+  return !IsDeadCheck(obj->GetIsolate(), location) &&
+      ApiCheck(index < obj->GetInternalFieldCount(),
+               location,
+               "Internal field out of bounds");
+}
+
+
+Local<Value> v8::Object::SlowGetInternalField(int index) {
   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  if (IsDeadCheck(obj->GetIsolate(), "v8::Object::GetInternalField()")) {
-    return Local<Value>();
-  }
-  if (!ApiCheck(index < obj->GetInternalFieldCount(),
-                "v8::Object::GetInternalField()",
-                "Reading internal field out of bounds")) {
-    return Local<Value>();
-  }
-  i::Handle<i::Object> value(obj->GetInternalField(index));
-  Local<Value> result = Utils::ToLocal(value);
-#ifdef DEBUG
-  Local<Value> unchecked = UncheckedGetInternalField(index);
-  ASSERT(unchecked.IsEmpty() || (unchecked == result));
-#endif
-  return result;
+  const char* location = "v8::Object::GetInternalField()";
+  if (!InternalFieldOK(obj, index, location)) return Local<Value>();
+  i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate());
+  return Utils::ToLocal(value);
 }
 
 
 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  i::Isolate* isolate = obj->GetIsolate();
-  if (IsDeadCheck(isolate, "v8::Object::SetInternalField()")) {
-    return;
-  }
-  if (!ApiCheck(index < obj->GetInternalFieldCount(),
-                "v8::Object::SetInternalField()",
-                "Writing internal field out of bounds")) {
-    return;
-  }
-  ENTER_V8(isolate);
+  const char* location = "v8::Object::SetInternalField()";
+  if (!InternalFieldOK(obj, index, location)) return;
   i::Handle<i::Object> val = Utils::OpenHandle(*value);
   obj->SetInternalField(index, *val);
+  ASSERT_EQ(value, GetInternalField(index));
 }
 
 
-static bool CanBeEncodedAsSmi(void* ptr) {
-  const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
-  return ((address & i::kEncodablePointerMask) == 0);
+void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
+  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
+  if (!InternalFieldOK(obj, index, location)) return NULL;
+  return DecodeSmiToAligned(obj->GetInternalField(index), location);
 }
 
 
-static i::Smi* EncodeAsSmi(void* ptr) {
-  ASSERT(CanBeEncodedAsSmi(ptr));
-  const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
-  i::Smi* result = reinterpret_cast<i::Smi*>(address << i::kPointerToSmiShift);
-  ASSERT(i::Internals::HasSmiTag(result));
-  ASSERT_EQ(result, i::Smi::FromInt(result->value()));
-  ASSERT_EQ(ptr, i::Internals::GetExternalPointerFromSmi(result));
-  return result;
+void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
+  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  const char* location = "v8::Object::SetAlignedPointerInInternalField()";
+  if (!InternalFieldOK(obj, index, location)) return;
+  obj->SetInternalField(index, EncodeAlignedAsSmi(value, location));
+  ASSERT_EQ(value, GetAlignedPointerFromInternalField(index));
 }
 
 
-void v8::Object::SetPointerInInternalField(int index, void* value) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
-  if (CanBeEncodedAsSmi(value)) {
-    Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value));
-  } else {
-    HandleScope scope;
-    i::Handle<i::Foreign> foreign =
-        isolate->factory()->NewForeign(
-            reinterpret_cast<i::Address>(value), i::TENURED);
-    if (!foreign.is_null()) {
-      Utils::OpenHandle(this)->SetInternalField(index, *foreign);
-    }
-  }
-  ASSERT_EQ(value, GetPointerFromInternalField(index));
+static void* ExternalValue(i::Object* obj) {
+  // Obscure semantics for undefined, but somehow checked in our unit tests...
+  if (obj->IsUndefined()) return NULL;
+  i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0);
+  return i::Foreign::cast(foreign)->foreign_address();
+}
+
+
+void* Object::GetPointerFromInternalField(int index) {
+  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  const char* location = "v8::Object::GetPointerFromInternalField()";
+  if (!InternalFieldOK(obj, index, location)) return NULL;
+  return ExternalValue(obj->GetInternalField(index));
 }
 
 
@@ -4698,74 +4734,20 @@ bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
 }
 
 
-static Local<External> ExternalNewImpl(void* data) {
-  return Utils::ToLocal(FACTORY->NewForeign(static_cast<i::Address>(data)));
-}
-
-static void* ExternalValueImpl(i::Handle<i::Object> obj) {
-  return reinterpret_cast<void*>(i::Foreign::cast(*obj)->foreign_address());
-}
-
-
-Local<Value> v8::External::Wrap(void* data) {
-  i::Isolate* isolate = i::Isolate::Current();
-  STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
-  EnsureInitializedForIsolate(isolate, "v8::External::Wrap()");
-  LOG_API(isolate, "External::Wrap");
-  ENTER_V8(isolate);
-
-  v8::Local<v8::Value> result = CanBeEncodedAsSmi(data)
-      ? Utils::ToLocal(i::Handle<i::Object>(EncodeAsSmi(data)))
-      : v8::Local<v8::Value>(ExternalNewImpl(data));
-
-  ASSERT_EQ(data, Unwrap(result));
-  return result;
-}
-
-
-void* v8::Object::SlowGetPointerFromInternalField(int index) {
-  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
-  i::Object* value = obj->GetInternalField(index);
-  if (value->IsSmi()) {
-    return i::Internals::GetExternalPointerFromSmi(value);
-  } else if (value->IsForeign()) {
-    return reinterpret_cast<void*>(i::Foreign::cast(value)->foreign_address());
-  } else {
-    return NULL;
-  }
-}
-
-
-void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
-  if (IsDeadCheck(i::Isolate::Current(), "v8::External::Unwrap()")) return 0;
-  i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
-  void* result;
-  if (obj->IsSmi()) {
-    result = i::Internals::GetExternalPointerFromSmi(*obj);
-  } else if (obj->IsForeign()) {
-    result = ExternalValueImpl(obj);
-  } else {
-    result = NULL;
-  }
-  ASSERT_EQ(result, QuickUnwrap(wrapper));
-  return result;
-}
-
-
-Local<External> v8::External::New(void* data) {
-  STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
+Local<External> v8::External::New(void* value) {
+  STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
   i::Isolate* isolate = i::Isolate::Current();
   EnsureInitializedForIsolate(isolate, "v8::External::New()");
   LOG_API(isolate, "External::New");
   ENTER_V8(isolate);
-  return ExternalNewImpl(data);
+  i::Handle<i::JSObject> external = isolate->factory()->NewExternal(value);
+  return Utils::ExternalToLocal(external);
 }
 
 
 void* External::Value() const {
-  if (IsDeadCheck(i::Isolate::Current(), "v8::External::Value()")) return 0;
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  return ExternalValueImpl(obj);
+  if (IsDeadCheck(i::Isolate::Current(), "v8::External::Value()")) return NULL;
+  return ExternalValue(*Utils::OpenHandle(this));
 }
 
 
index 7197b6cb546b83959c7714309c71dde278effeb0..ca2240b640e068974634926ab51879ee3f49164f 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -201,8 +201,6 @@ class Utils {
       v8::internal::Handle<v8::internal::JSObject> obj);
   static inline Local<Array> ToLocal(
       v8::internal::Handle<v8::internal::JSArray> obj);
-  static inline Local<External> ToLocal(
-      v8::internal::Handle<v8::internal::Foreign> obj);
   static inline Local<Message> MessageToLocal(
       v8::internal::Handle<v8::internal::Object> obj);
   static inline Local<StackTrace> StackTraceToLocal(
@@ -225,6 +223,8 @@ class Utils {
       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
   static inline Local<TypeSwitch> ToLocal(
       v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);
+  static inline Local<External> ExternalToLocal(
+      v8::internal::Handle<v8::internal::JSObject> obj);
 
 #define DECLARE_OPEN_HANDLE(From, To) \
   static inline v8::internal::Handle<v8::internal::To> \
@@ -268,7 +268,6 @@ MAKE_TO_LOCAL(ToLocal, String, String)
 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
 MAKE_TO_LOCAL(ToLocal, JSObject, Object)
 MAKE_TO_LOCAL(ToLocal, JSArray, Array)
-MAKE_TO_LOCAL(ToLocal, Foreign, External)
 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
 MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
@@ -280,6 +279,7 @@ MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
 MAKE_TO_LOCAL(NumberToLocal, Object, Number)
 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
+MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
 
 #undef MAKE_TO_LOCAL
 
index 5e1f80ebc9de7147dee429021eb37dc5a0017261..5d246e0751021fc7cce60d3f59303a5408f6029d 100644 (file)
@@ -1240,8 +1240,9 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
   // Initialize the out of memory slot.
   native_context()->set_out_of_memory(heap->false_value());
 
-  // Initialize the data slot.
-  native_context()->set_data(heap->undefined_value());
+  // Initialize the embedder data slot.
+  Handle<FixedArray> embedder_data = factory->NewFixedArray(2);
+  native_context()->set_embedder_data(*embedder_data);
 
   {
     // Initialize the random seed slot.
index 86374371e9b81de642cb528ad2b9a89e76c2c7f1..97365e0d582aa0c0a4b1ea894edfebe7800039de 100644 (file)
@@ -432,7 +432,9 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
 
   ASSERT(!isolate->native_context().is_null());
   Handle<Script> script = info->script();
-  script->set_context_data((*isolate->native_context())->data());
+  // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
+  FixedArray* array = isolate->native_context()->embedder_data();
+  script->set_context_data(array->get(0));
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   if (info->is_eval()) {
index 28e4af53682b2fa6a55623914720d7939bbd0285..53a7c2d460b46b74532b41c14acda1af647b9365 100644 (file)
@@ -152,7 +152,7 @@ enum BindingFlags {
   V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
   V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \
   V(MAP_CACHE_INDEX, Object, map_cache) \
-  V(CONTEXT_DATA_INDEX, Object, data) \
+  V(EMBEDDER_DATA_INDEX, FixedArray, embedder_data) \
   V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
   V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
     error_message_for_code_gen_from_strings) \
@@ -281,7 +281,7 @@ class Context: public FixedArray {
     OPAQUE_REFERENCE_FUNCTION_INDEX,
     CONTEXT_EXTENSION_FUNCTION_INDEX,
     OUT_OF_MEMORY_INDEX,
-    CONTEXT_DATA_INDEX,
+    EMBEDDER_DATA_INDEX,
     ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
     ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
     TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
@@ -446,6 +446,9 @@ class Context: public FixedArray {
   static bool IsBootstrappingOrValidParentContext(Object* object, Context* kid);
   static bool IsBootstrappingOrGlobalObject(Object* object);
 #endif
+
+  STATIC_CHECK(kHeaderSize == Internals::kContextHeaderSize);
+  STATIC_CHECK(EMBEDDER_DATA_INDEX == Internals::kContextEmbedderDataIndex);
 };
 
 } }  // namespace v8::internal
index a2bb9391ee64fb2bf8fe7332c39353d8fef19999..32a1755e3ba80f81f67974287d65eda8264666ea 100644 (file)
@@ -525,6 +525,12 @@ Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
 }
 
 
+Handle<FixedArray> Factory::CopySizeFixedArray(Handle<FixedArray> array,
+                                               int new_length) {
+  CALL_HEAP_FUNCTION(isolate(), array->CopySize(new_length), FixedArray);
+}
+
+
 Handle<FixedDoubleArray> Factory::CopyFixedDoubleArray(
     Handle<FixedDoubleArray> array) {
   CALL_HEAP_FUNCTION(isolate(), array->Copy(), FixedDoubleArray);
@@ -870,6 +876,13 @@ Handle<ScopeInfo> Factory::NewScopeInfo(int length) {
 }
 
 
+Handle<JSObject> Factory::NewExternal(void* value) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateExternal(value),
+                     JSObject);
+}
+
+
 Handle<Code> Factory::NewCode(const CodeDesc& desc,
                               Code::Flags flags,
                               Handle<Object> self_ref,
index 51065aac41821a1c6b1e460d8dd716dee09f5143..95a33f90b4b6626a837d1306dd39515b036c4642 100644 (file)
@@ -239,6 +239,9 @@ class Factory {
 
   Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
 
+  Handle<FixedArray> CopySizeFixedArray(Handle<FixedArray> array,
+                                        int new_length);
+
   Handle<FixedDoubleArray> CopyFixedDoubleArray(
       Handle<FixedDoubleArray> array);
 
@@ -325,6 +328,8 @@ class Factory {
 
   Handle<ScopeInfo> NewScopeInfo(int length);
 
+  Handle<JSObject> NewExternal(void* value);
+
   Handle<Code> NewCode(const CodeDesc& desc,
                        Code::Flags flags,
                        Handle<Object> self_reference,
index 468a01d6949bc2cdf20928dcb4eb33da3af36400..76084cfd58ac23b7b3a350049830a80bb9f664ed 100644 (file)
@@ -2531,6 +2531,14 @@ bool Heap::CreateInitialMaps() {
   }
   set_message_object_map(Map::cast(obj));
 
+  Map* external_map;
+  { MaybeObject* maybe_obj =
+        AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize);
+    if (!maybe_obj->To(&external_map)) return false;
+  }
+  external_map->set_is_extensible(false);
+  set_external_map(external_map);
+
   ASSERT(!InNewSpace(empty_fixed_array()));
   return true;
 }
@@ -5133,6 +5141,20 @@ MaybeObject* Heap::AllocateScopeInfo(int length) {
 }
 
 
+MaybeObject* Heap::AllocateExternal(void* value) {
+  Foreign* foreign;
+  { MaybeObject* maybe_result = AllocateForeign(static_cast<Address>(value));
+    if (!maybe_result->To(&foreign)) return maybe_result;
+  }
+  JSObject* external;
+  { MaybeObject* maybe_result = AllocateJSObjectFromMap(external_map());
+    if (!maybe_result->To(&external)) return maybe_result;
+  }
+  external->SetInternalField(0, foreign);
+  return external;
+}
+
+
 MaybeObject* Heap::AllocateStruct(InstanceType type) {
   Map* map;
   switch (type) {
index da78b18a512764dae3510e6fcc6dfaa66665e129..297b24f7a60c97395210d67e1136c70234399ad2 100644 (file)
@@ -154,7 +154,8 @@ namespace internal {
   V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset)     \
   V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset)           \
   V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset)                 \
-  V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset)
+  V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset)                 \
+  V(Map, external_map, ExternalMap)
 
 #define ROOT_LIST(V)                                  \
   STRONG_ROOT_LIST(V)                                 \
@@ -664,6 +665,9 @@ class Heap {
   // Allocates a serialized scope info.
   MUST_USE_RESULT MaybeObject* AllocateScopeInfo(int length);
 
+  // Allocates an External object for v8's external API.
+  MUST_USE_RESULT MaybeObject* AllocateExternal(void* value);
+
   // Allocates an empty PolymorphicCodeCache.
   MUST_USE_RESULT MaybeObject* AllocatePolymorphicCodeCache();
 
index 4e7d8f8c08702943ef60fb3692b5ceb56482ec5d..bbd1a09a32039b48fb0cd0e87d4164ddc98cb0aa 100644 (file)
@@ -134,6 +134,14 @@ bool Object::IsFixedArrayBase() {
 }
 
 
+// External objects are not extensible, so the map check is enough.
+bool Object::IsExternal() {
+  return Object::IsHeapObject() &&
+      HeapObject::cast(this)->map() ==
+      HeapObject::cast(this)->GetHeap()->external_map();
+}
+
+
 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
   // There is a constraint on the object; check.
   if (!this->IsJSObject()) return false;
index 0d1a69cb9882985fa282c4e2f3dc4a5fa98c9523..50018bfb70e0f1ccc59858ae611a5b12f1f7b544 100644 (file)
@@ -887,6 +887,7 @@ class Object : public MaybeObject {
 #undef IS_TYPE_FUNCTION_DECL
 
   inline bool IsFixedArrayBase();
+  inline bool IsExternal();
 
   // Returns true if this object is an instance of the specified
   // function template.
@@ -2410,6 +2411,8 @@ class FixedArray: public FixedArrayBase {
                                                   Object* value);
 
  private:
+  STATIC_CHECK(kHeaderSize == Internals::kFixedArrayHeaderSize);
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
 };
 
index 9839edf7e24fb56b713e02d8c85f3889a7a920b2..25ce2ba2bdfefbdbc338e5ff367193045f37c9c8 100644 (file)
@@ -1988,7 +1988,7 @@ void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) {
               "(context func. result caches)");
     TagObject(context->normalized_map_cache(), "(context norm. map cache)");
     TagObject(context->runtime_context(), "(runtime context)");
-    TagObject(context->data(), "(context data)");
+    TagObject(context->embedder_data(), "(context data)");
     NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD);
 #undef EXTRACT_CONTEXT_FIELD
     for (int i = Context::FIRST_WEAK_SLOT;
index 89c74304f227ce8bdd26c9a3ded95bd4f68473a1..84c0612eb665bd53869d193c560f20e2febdf758 100644 (file)
@@ -25,6 +25,9 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// We want to test our deprecated API entries, too.
+#define V8_DISABLE_DEPRECATIONS 1
+
 #include <limits.h>
 
 #ifndef WIN32
@@ -2056,6 +2059,99 @@ THREADED_TEST(InternalFieldsNativePointersAndExternal) {
 }
 
 
+static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
+                                               void* value) {
+  CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
+  obj->SetPointerInInternalField(0, value);
+  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CHECK_EQ(value, obj->GetPointerFromInternalField(0));
+}
+
+
+THREADED_TEST(InternalFieldsAlignedPointers) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
+  instance_templ->SetInternalFieldCount(1);
+  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
+  CHECK_EQ(1, obj->InternalFieldCount());
+
+  CheckAlignedPointerInInternalField(obj, NULL);
+
+  int* heap_allocated = new int[100];
+  CheckAlignedPointerInInternalField(obj, heap_allocated);
+  delete[] heap_allocated;
+
+  int stack_allocated[100];
+  CheckAlignedPointerInInternalField(obj, stack_allocated);
+
+  void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
+  CheckAlignedPointerInInternalField(obj, huge);
+}
+
+
+static void CheckAlignedPointerInEmbedderData(LocalContext* env,
+                                              int index,
+                                              void* value) {
+  CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
+  (*env)->SetAlignedPointerInEmbedderData(index, value);
+  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
+}
+
+
+static void* AlignedTestPointer(int i) {
+  return reinterpret_cast<void*>(i * 1234);
+}
+
+
+THREADED_TEST(EmbedderDataAlignedPointers) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CheckAlignedPointerInEmbedderData(&env, 0, NULL);
+
+  int* heap_allocated = new int[100];
+  CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
+  delete[] heap_allocated;
+
+  int stack_allocated[100];
+  CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
+
+  void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
+  CheckAlignedPointerInEmbedderData(&env, 3, huge);
+
+  // Test growing of the embedder data's backing store.
+  for (int i = 0; i < 100; i++) {
+    env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
+  }
+  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
+  for (int i = 0; i < 100; i++) {
+    CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
+  }
+}
+
+
+static void CheckEmbedderData(LocalContext* env,
+                              int index,
+                              v8::Handle<Value> data) {
+  (*env)->SetEmbedderData(index, data);
+  CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
+}
+
+THREADED_TEST(EmbedderData) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CheckEmbedderData(&env, 3, v8::String::New("The quick brown fox jumps"));
+  CheckEmbedderData(&env, 2, v8::String::New("over the lazy dog."));
+  CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
+  CheckEmbedderData(&env, 0, v8::Boolean::New(true));
+}
+
+
 THREADED_TEST(IdentityHash) {
   v8::HandleScope scope;
   LocalContext env;
index f2253e3a9d399d8593e35dae7c3cf7fb971d5f7f..a719a62a373684f7c5528b32fc3938de91023551 100644 (file)
@@ -27,6 +27,9 @@
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
 
+// TODO(svenpanne): Do not use Context::GetData and Context::SetData.
+#define V8_DISABLE_DEPRECATIONS 1
+
 #include <stdlib.h>
 
 #include "v8.h"
index 6fc601213c67bc32e268a10493e442b102b373e8..e398cbb307559450d88b9c34c970ee94bc87d969 100644 (file)
@@ -190,7 +190,8 @@ v8::Handle<Integer> DeclarationContext::HandleQuery(Local<String> key,
 
 
 DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) {
-  return static_cast<DeclarationContext*>(External::Unwrap(info.Data()));
+  void* value = External::Cast(*info.Data())->Value();
+  return static_cast<DeclarationContext*>(value);
 }
 
 
index 46ead5e465559c27563812dfc5e032e8efa46eba..6a57e5b4dc3bfb20bac5a19444afc5c365aad9d0 100755 (executable)
@@ -863,80 +863,82 @@ INSTANCE_TYPES = {
 # }
 # printf("}\n");
 KNOWN_MAPS = {
-  0x08081: (134, "ByteArrayMap"),
-  0x080a1: (128, "MetaMap"),
-  0x080c1: (130, "OddballMap"),
-  0x080e1: (163, "FixedArrayMap"),
-  0x08101: (68, "AsciiSymbolMap"),
-  0x08121: (132, "HeapNumberMap"),
-  0x08141: (135, "FreeSpaceMap"),
-  0x08161: (146, "OnePointerFillerMap"),
-  0x08181: (146, "TwoPointerFillerMap"),
-  0x081a1: (131, "GlobalPropertyCellMap"),
-  0x081c1: (164, "SharedFunctionInfoMap"),
-  0x081e1: (4, "AsciiStringMap"),
-  0x08201: (163, "GlobalContextMap"),
-  0x08221: (129, "CodeMap"),
-  0x08241: (163, "ScopeInfoMap"),
-  0x08261: (163, "FixedCOWArrayMap"),
-  0x08281: (145, "FixedDoubleArrayMap"),
-  0x082a1: (163, "HashTableMap"),
-  0x082c1: (0, "StringMap"),
-  0x082e1: (64, "SymbolMap"),
-  0x08301: (1, "ConsStringMap"),
-  0x08321: (5, "ConsAsciiStringMap"),
-  0x08341: (3, "SlicedStringMap"),
-  0x08361: (7, "SlicedAsciiStringMap"),
-  0x08381: (65, "ConsSymbolMap"),
-  0x083a1: (69, "ConsAsciiSymbolMap"),
-  0x083c1: (66, "ExternalSymbolMap"),
-  0x083e1: (74, "ExternalSymbolWithAsciiDataMap"),
-  0x08401: (70, "ExternalAsciiSymbolMap"),
-  0x08421: (2, "ExternalStringMap"),
-  0x08441: (10, "ExternalStringWithAsciiDataMap"),
-  0x08461: (6, "ExternalAsciiStringMap"),
-  0x08481: (82, "ShortExternalSymbolMap"),
-  0x084a1: (90, "ShortExternalSymbolWithAsciiDataMap"),
-  0x084c1: (86, "ShortExternalAsciiSymbolMap"),
-  0x084e1: (18, "ShortExternalStringMap"),
-  0x08501: (26, "ShortExternalStringWithAsciiDataMap"),
-  0x08521: (22, "ShortExternalAsciiStringMap"),
-  0x08541: (0, "UndetectableStringMap"),
-  0x08561: (4, "UndetectableAsciiStringMap"),
-  0x08581: (144, "ExternalPixelArrayMap"),
-  0x085a1: (136, "ExternalByteArrayMap"),
-  0x085c1: (137, "ExternalUnsignedByteArrayMap"),
-  0x085e1: (138, "ExternalShortArrayMap"),
-  0x08601: (139, "ExternalUnsignedShortArrayMap"),
-  0x08621: (140, "ExternalIntArrayMap"),
-  0x08641: (141, "ExternalUnsignedIntArrayMap"),
-  0x08661: (142, "ExternalFloatArrayMap"),
-  0x08681: (143, "ExternalDoubleArrayMap"),
-  0x086a1: (163, "NonStrictArgumentsElementsMap"),
-  0x086c1: (163, "FunctionContextMap"),
-  0x086e1: (163, "CatchContextMap"),
-  0x08701: (163, "WithContextMap"),
-  0x08721: (163, "BlockContextMap"),
-  0x08741: (163, "ModuleContextMap"),
-  0x08761: (165, "JSMessageObjectMap"),
-  0x08781: (133, "ForeignMap"),
-  0x087a1: (170, "NeanderMap"),
-  0x087c1: (158, "PolymorphicCodeCacheMap"),
-  0x087e1: (156, "ScriptMap"),
-  0x08801: (147, "AccessorInfoMap"),
-  0x08821: (148, "AccessorPairMap"),
-  0x08841: (149, "AccessCheckInfoMap"),
-  0x08861: (150, "InterceptorInfoMap"),
-  0x08881: (151, "CallHandlerInfoMap"),
-  0x088a1: (152, "FunctionTemplateInfoMap"),
-  0x088c1: (153, "ObjectTemplateInfoMap"),
-  0x088e1: (154, "SignatureInfoMap"),
-  0x08901: (155, "TypeSwitchInfoMap"),
-  0x08921: (157, "CodeCacheMap"),
-  0x08941: (159, "TypeFeedbackInfoMap"),
-  0x08961: (160, "AliasedArgumentsEntryMap"),
-  0x08981: (161, "DebugInfoMap"),
-  0x089a1: (162, "BreakPointInfoMap"),
+  0x08081: (128, "MetaMap"),
+  0x080a5: (163, "FixedArrayMap"),
+  0x080c9: (130, "OddballMap"),
+  0x080ed: (163, "FixedCOWArrayMap"),
+  0x08111: (163, "ScopeInfoMap"),
+  0x08135: (132, "HeapNumberMap"),
+  0x08159: (133, "ForeignMap"),
+  0x0817d: (64, "SymbolMap"),
+  0x081a1: (68, "AsciiSymbolMap"),
+  0x081c5: (65, "ConsSymbolMap"),
+  0x081e9: (69, "ConsAsciiSymbolMap"),
+  0x0820d: (66, "ExternalSymbolMap"),
+  0x08231: (74, "ExternalSymbolWithAsciiDataMap"),
+  0x08255: (70, "ExternalAsciiSymbolMap"),
+  0x08279: (82, "ShortExternalSymbolMap"),
+  0x0829d: (90, "ShortExternalSymbolWithAsciiDataMap"),
+  0x082c1: (86, "ShortExternalAsciiSymbolMap"),
+  0x082e5: (0, "StringMap"),
+  0x08309: (4, "AsciiStringMap"),
+  0x0832d: (1, "ConsStringMap"),
+  0x08351: (5, "ConsAsciiStringMap"),
+  0x08375: (3, "SlicedStringMap"),
+  0x08399: (7, "SlicedAsciiStringMap"),
+  0x083bd: (2, "ExternalStringMap"),
+  0x083e1: (10, "ExternalStringWithAsciiDataMap"),
+  0x08405: (6, "ExternalAsciiStringMap"),
+  0x08429: (18, "ShortExternalStringMap"),
+  0x0844d: (26, "ShortExternalStringWithAsciiDataMap"),
+  0x08471: (22, "ShortExternalAsciiStringMap"),
+  0x08495: (0, "UndetectableStringMap"),
+  0x084b9: (4, "UndetectableAsciiStringMap"),
+  0x084dd: (145, "FixedDoubleArrayMap"),
+  0x08501: (134, "ByteArrayMap"),
+  0x08525: (135, "FreeSpaceMap"),
+  0x08549: (144, "ExternalPixelArrayMap"),
+  0x0856d: (136, "ExternalByteArrayMap"),
+  0x08591: (137, "ExternalUnsignedByteArrayMap"),
+  0x085b5: (138, "ExternalShortArrayMap"),
+  0x085d9: (139, "ExternalUnsignedShortArrayMap"),
+  0x085fd: (140, "ExternalIntArrayMap"),
+  0x08621: (141, "ExternalUnsignedIntArrayMap"),
+  0x08645: (142, "ExternalFloatArrayMap"),
+  0x08669: (163, "NonStrictArgumentsElementsMap"),
+  0x0868d: (143, "ExternalDoubleArrayMap"),
+  0x086b1: (129, "CodeMap"),
+  0x086d5: (131, "GlobalPropertyCellMap"),
+  0x086f9: (146, "OnePointerFillerMap"),
+  0x0871d: (146, "TwoPointerFillerMap"),
+  0x08741: (147, "AccessorInfoMap"),
+  0x08765: (148, "AccessorPairMap"),
+  0x08789: (149, "AccessCheckInfoMap"),
+  0x087ad: (150, "InterceptorInfoMap"),
+  0x087d1: (151, "CallHandlerInfoMap"),
+  0x087f5: (152, "FunctionTemplateInfoMap"),
+  0x08819: (153, "ObjectTemplateInfoMap"),
+  0x0883d: (154, "SignatureInfoMap"),
+  0x08861: (155, "TypeSwitchInfoMap"),
+  0x08885: (156, "ScriptMap"),
+  0x088a9: (157, "CodeCacheMap"),
+  0x088cd: (158, "PolymorphicCodeCacheMap"),
+  0x088f1: (159, "TypeFeedbackInfoMap"),
+  0x08915: (160, "AliasedArgumentsEntryMap"),
+  0x08939: (161, "DebugInfoMap"),
+  0x0895d: (162, "BreakPointInfoMap"),
+  0x08981: (163, "HashTableMap"),
+  0x089a5: (163, "FunctionContextMap"),
+  0x089c9: (163, "CatchContextMap"),
+  0x089ed: (163, "WithContextMap"),
+  0x08a11: (163, "BlockContextMap"),
+  0x08a35: (163, "ModuleContextMap"),
+  0x08a59: (163, "GlobalContextMap"),
+  0x08a7d: (163, "NativeContextMap"),
+  0x08aa1: (164, "SharedFunctionInfoMap"),
+  0x08ac5: (165, "JSMessageObjectMap"),
+  0x08ae9: (170, "ExternalMap"),
+  0x08b0d: (170, "NeanderMap"),
 }