static External* Cast(Value* obj);
void* Value() const;
private:
+ enum {
+ kAlignedPointerMask = 3,
+ kAlignedPointerShift = 2
+ };
External();
};
External* External::Cast(v8::Value* that) {
if (IsDeadCheck("v8::External::Cast()")) return 0;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsProxy(),
+ ApiCheck(obj->IsProxy() || obj->IsSmi(),
"v8::External::Cast()",
"Could not convert to external");
return static_cast<External*>(that);
void* External::Value() const {
if (IsDeadCheck("v8::External::Value()")) return 0;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ if (obj->IsSmi()) {
+ // The external value was an aligned pointer.
+ return reinterpret_cast<void*>(
+ i::Smi::cast(*obj)->value() << kAlignedPointerShift);
+ }
return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
}
STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
LOG_API("External::New");
EnsureInitialized("v8::External::New()");
- i::Handle<i::Proxy> obj = i::Factory::NewProxy(static_cast<i::Address>(data));
- return Utils::ToLocal(obj);
+ if ((reinterpret_cast<intptr_t>(data) & kAlignedPointerMask) == 0) {
+ uintptr_t data_ptr = reinterpret_cast<uintptr_t>(data);
+ int data_value = static_cast<int>(data_ptr >> kAlignedPointerShift);
+ STATIC_ASSERT(sizeof(data_ptr) == sizeof(data_value));
+ i::Handle<i::Smi> obj(i::Smi::FromInt(data_value));
+ return Utils::ToLocal(obj);
+ }
+ return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
}
v8::internal::Handle<v8::internal::JSArray> obj);
static inline Local<External> ToLocal(
v8::internal::Handle<v8::internal::Proxy> obj);
+ static inline Local<External> ToLocal(
+ v8::internal::Handle<v8::internal::Smi> obj);
static inline Local<Message> MessageToLocal(
v8::internal::Handle<v8::internal::Object> obj);
static inline Local<Number> NumberToLocal(
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)
CHECK_EQ(x, 3);
*ptr = 10;
CHECK_EQ(x, 10);
+
+ // Make sure unaligned pointers are wrapped properly.
+ char* data = "0123456789";
+ Local<v8::External> zero = v8::External::New(&data[0]);
+ Local<v8::External> one = v8::External::New(&data[1]);
+ Local<v8::External> two = v8::External::New(&data[2]);
+ Local<v8::External> three = v8::External::New(&data[3]);
+
+ char* char_ptr = reinterpret_cast<char*>(zero->Value());
+ CHECK_EQ('0', *char_ptr);
+ char_ptr = reinterpret_cast<char*>(one->Value());
+ CHECK_EQ('1', *char_ptr);
+ char_ptr = reinterpret_cast<char*>(two->Value());
+ CHECK_EQ('2', *char_ptr);
+ char_ptr = reinterpret_cast<char*>(three->Value());
+ CHECK_EQ('3', *char_ptr);
}