From 7b50c072f9a72d73a44b9ef8e0081cf5e4e86648 Mon Sep 17 00:00:00 2001 From: "iposva@chromium.org" Date: Mon, 23 Mar 2009 19:51:10 +0000 Subject: [PATCH] Add a new C++ pointer wrapping API to External to not dilute the External::Cast. Review URL: http://codereview.chromium.org/52021 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1578 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 17 +++++++---- src/api.cc | 64 +++++++++++++++++++++++++++++------------ src/api.h | 3 -- test/cctest/test-api.cc | 16 +++++------ 4 files changed, 65 insertions(+), 35 deletions(-) diff --git a/include/v8.h b/include/v8.h index dfba9dbae..a6851c922 100644 --- a/include/v8.h +++ b/include/v8.h @@ -1141,20 +1141,25 @@ class V8EXPORT Function : public Object { /** - * A JavaScript value that wraps a c++ void*. This type of value is - * mainly used to associate c++ data structures with JavaScript + * 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. */ class V8EXPORT External : public Value { public: + static Local Wrap(void* data); + static void* Unwrap(Handle obj); + static Local New(void* value); static External* Cast(Value* obj); void* Value() const; private: - enum { - kAlignedPointerMask = 3, - kAlignedPointerShift = 2 - }; External(); }; diff --git a/src/api.cc b/src/api.cc index 5ae13a12d..27efc4e0d 100644 --- a/src/api.cc +++ b/src/api.cc @@ -1447,7 +1447,7 @@ Local Value::ToInteger() const { External* External::Cast(v8::Value* that) { if (IsDeadCheck("v8::External::Cast()")) return 0; i::Handle obj = Utils::OpenHandle(that); - ApiCheck(obj->IsProxy() || obj->IsSmi(), + ApiCheck(obj->IsProxy(), "v8::External::Cast()", "Could not convert to external"); return static_cast(that); @@ -2226,18 +2226,6 @@ int32_t Int32::Value() const { } -void* External::Value() const { - if (IsDeadCheck("v8::External::Value()")) return 0; - i::Handle obj = Utils::OpenHandle(this); - if (obj->IsSmi()) { - // The external value was an aligned pointer. - return reinterpret_cast( - i::Smi::cast(*obj)->value() << kAlignedPointerShift); - } - return reinterpret_cast(i::Proxy::cast(*obj)->proxy()); -} - - int v8::Object::InternalFieldCount() { if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0; i::Handle obj = Utils::OpenHandle(this); @@ -2468,18 +2456,58 @@ bool FunctionTemplate::HasInstance(v8::Handle value) { } -Local v8::External::New(void* data) { +static Local ExternalNewImpl(void* data) { + return Utils::ToLocal(i::Factory::NewProxy(static_cast(data))); +} + +static void* ExternalValueImpl(i::Handle obj) { + return reinterpret_cast(i::Proxy::cast(*obj)->proxy()); +} + + +static const intptr_t kAlignedPointerMask = 3; +static const int kAlignedPointerShift = 2; + + +Local v8::External::Wrap(void* data) { STATIC_ASSERT(sizeof(data) == sizeof(i::Address)); - LOG_API("External::New"); - EnsureInitialized("v8::External::New()"); + LOG_API("External::Wrap"); + EnsureInitialized("v8::External::Wrap()"); if ((reinterpret_cast(data) & kAlignedPointerMask) == 0) { uintptr_t data_ptr = reinterpret_cast(data); int data_value = static_cast(data_ptr >> kAlignedPointerShift); STATIC_ASSERT(sizeof(data_ptr) == sizeof(data_value)); - i::Handle obj(i::Smi::FromInt(data_value)); + i::Handle obj(i::Smi::FromInt(data_value)); return Utils::ToLocal(obj); } - return Utils::ToLocal(i::Factory::NewProxy(static_cast(data))); + return ExternalNewImpl(data); +} + + +void* v8::External::Unwrap(v8::Handle value) { + if (IsDeadCheck("v8::External::Unwrap()")) return 0; + i::Handle obj = Utils::OpenHandle(*value); + if (obj->IsSmi()) { + // The external value was an aligned pointer. + uintptr_t result = i::Smi::cast(*obj)->value() << kAlignedPointerShift; + return reinterpret_cast(result); + } + return ExternalValueImpl(obj); +} + + +Local v8::External::New(void* data) { + STATIC_ASSERT(sizeof(data) == sizeof(i::Address)); + LOG_API("External::New"); + EnsureInitialized("v8::External::New()"); + return ExternalNewImpl(data); +} + + +void* External::Value() const { + if (IsDeadCheck("v8::External::Value()")) return 0; + i::Handle obj = Utils::OpenHandle(this); + return ExternalValueImpl(obj); } diff --git a/src/api.h b/src/api.h index 27ec3415d..85b13ec9a 100644 --- a/src/api.h +++ b/src/api.h @@ -181,8 +181,6 @@ class Utils { v8::internal::Handle obj); static inline Local ToLocal( v8::internal::Handle obj); - static inline Local ToLocal( - v8::internal::Handle obj); static inline Local MessageToLocal( v8::internal::Handle obj); static inline Local NumberToLocal( @@ -258,7 +256,6 @@ MAKE_TO_LOCAL(ToLocal, String, String) MAKE_TO_LOCAL(ToLocal, JSObject, Object) MAKE_TO_LOCAL(ToLocal, JSArray, Array) MAKE_TO_LOCAL(ToLocal, Proxy, External) -MAKE_TO_LOCAL(ToLocal, Smi, External) MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate) MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate) MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature) diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index ed0aab635..1f0e955dd 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -1342,18 +1342,18 @@ THREADED_TEST(External) { // Make sure unaligned pointers are wrapped properly. char* data = i::StrDup("0123456789"); - Local zero = v8::External::New(&data[0]); - Local one = v8::External::New(&data[1]); - Local two = v8::External::New(&data[2]); - Local three = v8::External::New(&data[3]); + Local zero = v8::External::Wrap(&data[0]); + Local one = v8::External::Wrap(&data[1]); + Local two = v8::External::Wrap(&data[2]); + Local three = v8::External::Wrap(&data[3]); - char* char_ptr = reinterpret_cast(zero->Value()); + char* char_ptr = reinterpret_cast(v8::External::Unwrap(zero)); CHECK_EQ('0', *char_ptr); - char_ptr = reinterpret_cast(one->Value()); + char_ptr = reinterpret_cast(v8::External::Unwrap(one)); CHECK_EQ('1', *char_ptr); - char_ptr = reinterpret_cast(two->Value()); + char_ptr = reinterpret_cast(v8::External::Unwrap(two)); CHECK_EQ('2', *char_ptr); - char_ptr = reinterpret_cast(three->Value()); + char_ptr = reinterpret_cast(v8::External::Unwrap(three)); CHECK_EQ('3', *char_ptr); i::DeleteArray(data); } -- 2.34.1