Re-land rev. 12849 and 12868 (Heavy cleanup of the external pointer API + related fix).
Review URL: https://codereview.chromium.org/11365224 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12945 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ce682a2489
commit
673924413f
268
include/v8.h
268
include/v8.h
@ -76,6 +76,17 @@
|
||||
|
||||
#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.
|
||||
*/
|
||||
@ -1601,16 +1612,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.
|
||||
*/
|
||||
V8EXPORT V8_DEPRECATED(void* GetPointerFromInternalField(int index));
|
||||
|
||||
/** Sets a native pointer in an internal field. */
|
||||
V8EXPORT void SetPointerInInternalField(int index, void* value);
|
||||
/**
|
||||
* 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));
|
||||
|
||||
/**
|
||||
* 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);
|
||||
@ -1741,14 +1777,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);
|
||||
};
|
||||
|
||||
|
||||
@ -1959,29 +1989,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);
|
||||
};
|
||||
|
||||
|
||||
@ -3770,12 +3793,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.
|
||||
*/
|
||||
void SetData(Handle<Value> data);
|
||||
Local<Value> GetData();
|
||||
V8_DEPRECATED(inline Local<Value> GetData());
|
||||
|
||||
/**
|
||||
* Sets embedder data with index 0. Deprecated, use SetEmbedderData with index
|
||||
* 0 instead.
|
||||
*/
|
||||
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
|
||||
@ -3824,6 +3880,9 @@ class V8EXPORT Context {
|
||||
friend class Script;
|
||||
friend class Object;
|
||||
friend class Function;
|
||||
|
||||
Local<Value> SlowGetEmbedderData(int index);
|
||||
void* SlowGetAlignedPointerFromEmbedderData(int index);
|
||||
};
|
||||
|
||||
|
||||
@ -4057,11 +4116,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.
|
||||
@ -4073,26 +4127,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
|
||||
@ -4110,6 +4149,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;
|
||||
@ -4122,7 +4164,7 @@ class Internals {
|
||||
static const int kNullValueRootIndex = 7;
|
||||
static const int kTrueValueRootIndex = 8;
|
||||
static const int kFalseValueRootIndex = 9;
|
||||
static const int kEmptySymbolRootIndex = 118;
|
||||
static const int kEmptySymbolRootIndex = 119;
|
||||
|
||||
static const int kJSObjectType = 0xaa;
|
||||
static const int kFirstNonstringType = 0x80;
|
||||
@ -4137,10 +4179,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);
|
||||
}
|
||||
@ -4156,21 +4194,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;
|
||||
@ -4204,6 +4227,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; }
|
||||
@ -4418,63 +4454,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);
|
||||
}
|
||||
|
||||
|
||||
@ -4666,6 +4679,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);
|
||||
@ -4742,6 +4765,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
|
||||
|
250
src/api.cc
250
src/api.cc
@ -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.
|
||||
@ -810,33 +813,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>();
|
||||
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>();
|
||||
}
|
||||
ASSERT(env->IsNativeContext());
|
||||
if (!env->IsNativeContext()) {
|
||||
return Local<Value>();
|
||||
}
|
||||
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()",
|
||||
@ -2235,7 +2282,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();
|
||||
}
|
||||
|
||||
|
||||
@ -2468,8 +2515,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");
|
||||
}
|
||||
@ -4233,75 +4279,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));
|
||||
}
|
||||
|
||||
|
||||
@ -4740,74 +4776,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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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()) {
|
||||
|
@ -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) \
|
||||
@ -283,7 +283,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,
|
||||
@ -450,6 +450,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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
22
src/heap.cc
22
src/heap.cc
@ -2578,6 +2578,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;
|
||||
}
|
||||
@ -5217,6 +5225,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) {
|
||||
|
@ -155,7 +155,8 @@ namespace internal {
|
||||
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(JSObject, observation_state, ObservationState)
|
||||
V(JSObject, observation_state, ObservationState) \
|
||||
V(Map, external_map, ExternalMap)
|
||||
|
||||
#define ROOT_LIST(V) \
|
||||
STRONG_ROOT_LIST(V) \
|
||||
@ -665,6 +666,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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -907,6 +907,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.
|
||||
@ -2451,6 +2452,8 @@ class FixedArray: public FixedArrayBase {
|
||||
Object* value);
|
||||
|
||||
private:
|
||||
STATIC_CHECK(kHeaderSize == Internals::kFixedArrayHeaderSize);
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -863,80 +863,83 @@ 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"),
|
||||
0x08b31: (170, ""),
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user