Api inlining. Made some core functionality available in the api and

made inline versions of some hot functions.  Changed api to use
internal Object pointers rather than void pointers.

Speeds up getElementById by ~7%.
Review URL: http://codereview.chromium.org/173348

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2761 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
christian.plesner.hansen@gmail.com 2009-08-26 10:33:11 +00:00
parent a29d4e6762
commit af6c6a5533
14 changed files with 442 additions and 181 deletions

View File

@ -105,6 +105,9 @@ LIBRARY_FLAGS = {
'arch:x64' : {
'CPPDEFINES': ['V8_NATIVE_REGEXP']
}
},
'mode:debug': {
'CPPDEFINES': ['V8_ENABLE_CHECKS']
}
},
'gcc': {

View File

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

View File

@ -100,7 +100,9 @@ static i::HandleScopeImplementer thread_local;
static FatalErrorCallback exception_behavior = NULL;
int i::Internals::kJSObjectType = JS_OBJECT_TYPE;
int i::Internals::kFirstNonstringType = FIRST_NONSTRING_TYPE;
int i::Internals::kProxyType = PROXY_TYPE;
static void DefaultFatalErrorHandler(const char* location,
const char* message) {
@ -223,7 +225,8 @@ ImplementationUtilities::HandleScopeData*
#ifdef DEBUG
void ImplementationUtilities::ZapHandleRange(void** begin, void** end) {
void ImplementationUtilities::ZapHandleRange(i::Object** begin,
i::Object** end) {
i::HandleScope::ZapRange(begin, end);
}
#endif
@ -349,49 +352,47 @@ bool SetResourceConstraints(ResourceConstraints* constraints) {
}
void** V8::GlobalizeReference(void** obj) {
i::Object** V8::GlobalizeReference(i::Object** obj) {
if (IsDeadCheck("V8::Persistent::New")) return NULL;
LOG_API("Persistent::New");
i::Handle<i::Object> result =
i::GlobalHandles::Create(*reinterpret_cast<i::Object**>(obj));
return reinterpret_cast<void**>(result.location());
i::GlobalHandles::Create(*obj);
return result.location();
}
void V8::MakeWeak(void** object, void* parameters,
void V8::MakeWeak(i::Object** object, void* parameters,
WeakReferenceCallback callback) {
LOG_API("MakeWeak");
i::GlobalHandles::MakeWeak(reinterpret_cast<i::Object**>(object), parameters,
callback);
i::GlobalHandles::MakeWeak(object, parameters, callback);
}
void V8::ClearWeak(void** obj) {
void V8::ClearWeak(i::Object** obj) {
LOG_API("ClearWeak");
i::GlobalHandles::ClearWeakness(reinterpret_cast<i::Object**>(obj));
i::GlobalHandles::ClearWeakness(obj);
}
bool V8::IsGlobalNearDeath(void** obj) {
bool V8::IsGlobalNearDeath(i::Object** obj) {
LOG_API("IsGlobalNearDeath");
if (!i::V8::IsRunning()) return false;
return i::GlobalHandles::IsNearDeath(reinterpret_cast<i::Object**>(obj));
return i::GlobalHandles::IsNearDeath(obj);
}
bool V8::IsGlobalWeak(void** obj) {
bool V8::IsGlobalWeak(i::Object** obj) {
LOG_API("IsGlobalWeak");
if (!i::V8::IsRunning()) return false;
return i::GlobalHandles::IsWeak(reinterpret_cast<i::Object**>(obj));
return i::GlobalHandles::IsWeak(obj);
}
void V8::DisposeGlobal(void** obj) {
void V8::DisposeGlobal(i::Object** obj) {
LOG_API("DisposeGlobal");
if (!i::V8::IsRunning()) return;
i::Object** ptr = reinterpret_cast<i::Object**>(obj);
if ((*ptr)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
i::GlobalHandles::Destroy(ptr);
if ((*obj)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
i::GlobalHandles::Destroy(obj);
}
// --- H a n d l e s ---
@ -415,9 +416,8 @@ int HandleScope::NumberOfHandles() {
}
void** v8::HandleScope::CreateHandle(void* value) {
return reinterpret_cast<void**>(
i::HandleScope::CreateHandle(reinterpret_cast<i::Object*>(value)));
i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
return i::HandleScope::CreateHandle(value);
}
@ -481,7 +481,7 @@ v8::Local<v8::Value> Context::GetData() {
}
void** v8::HandleScope::RawClose(void** value) {
i::Object** v8::HandleScope::RawClose(i::Object** value) {
if (!ApiCheck(!is_closed_,
"v8::HandleScope::Close()",
"Local scope has already been closed")) {
@ -490,13 +490,13 @@ void** v8::HandleScope::RawClose(void** value) {
LOG_API("CloseHandleScope");
// Read the result before popping the handle block.
i::Object* result = reinterpret_cast<i::Object*>(*value);
i::Object* result = *value;
is_closed_ = true;
i::HandleScope::Leave(&previous_);
// Allocate a new handle on the previous handle block.
i::Handle<i::Object> handle(result);
return reinterpret_cast<void**>(handle.location());
return handle.location();
}
@ -1459,9 +1459,11 @@ bool Value::IsFunction() const {
}
bool Value::IsString() const {
bool Value::FullIsString() const {
if (IsDeadCheck("v8::Value::IsString()")) return false;
return Utils::OpenHandle(this)->IsString();
bool result = Utils::OpenHandle(this)->IsString();
ASSERT_EQ(result, QuickIsString());
return result;
}
@ -1613,83 +1615,75 @@ Local<Integer> Value::ToInteger() const {
}
External* External::Cast(v8::Value* that) {
if (IsDeadCheck("v8::External::Cast()")) return 0;
void External::CheckCast(v8::Value* that) {
if (IsDeadCheck("v8::External::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsProxy(),
"v8::External::Cast()",
"Could not convert to external");
return static_cast<External*>(that);
}
v8::Object* v8::Object::Cast(Value* that) {
if (IsDeadCheck("v8::Object::Cast()")) return 0;
void v8::Object::CheckCast(Value* that) {
if (IsDeadCheck("v8::Object::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsJSObject(),
"v8::Object::Cast()",
"Could not convert to object");
return static_cast<v8::Object*>(that);
}
v8::Function* v8::Function::Cast(Value* that) {
if (IsDeadCheck("v8::Function::Cast()")) return 0;
void v8::Function::CheckCast(Value* that) {
if (IsDeadCheck("v8::Function::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsJSFunction(),
"v8::Function::Cast()",
"Could not convert to function");
return static_cast<v8::Function*>(that);
}
v8::String* v8::String::Cast(v8::Value* that) {
if (IsDeadCheck("v8::String::Cast()")) return 0;
void v8::String::CheckCast(v8::Value* that) {
if (IsDeadCheck("v8::String::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsString(),
"v8::String::Cast()",
"Could not convert to string");
return static_cast<v8::String*>(that);
}
v8::Number* v8::Number::Cast(v8::Value* that) {
if (IsDeadCheck("v8::Number::Cast()")) return 0;
void v8::Number::CheckCast(v8::Value* that) {
if (IsDeadCheck("v8::Number::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsNumber(),
"v8::Number::Cast()",
"Could not convert to number");
return static_cast<v8::Number*>(that);
}
v8::Integer* v8::Integer::Cast(v8::Value* that) {
if (IsDeadCheck("v8::Integer::Cast()")) return 0;
void v8::Integer::CheckCast(v8::Value* that) {
if (IsDeadCheck("v8::Integer::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsNumber(),
"v8::Integer::Cast()",
"Could not convert to number");
return static_cast<v8::Integer*>(that);
}
v8::Array* v8::Array::Cast(Value* that) {
if (IsDeadCheck("v8::Array::Cast()")) return 0;
void v8::Array::CheckCast(Value* that) {
if (IsDeadCheck("v8::Array::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsJSArray(),
"v8::Array::Cast()",
"Could not convert to array");
return static_cast<v8::Array*>(that);
}
v8::Date* v8::Date::Cast(v8::Value* that) {
if (IsDeadCheck("v8::Date::Cast()")) return 0;
void v8::Date::CheckCast(v8::Value* that) {
if (IsDeadCheck("v8::Date::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
"v8::Date::Cast()",
"Could not convert to date");
return static_cast<v8::Date*>(that);
}
@ -2450,16 +2444,17 @@ bool v8::String::IsExternalAscii() const {
}
v8::String::ExternalStringResource*
v8::String::GetExternalStringResource() const {
EnsureInitialized("v8::String::GetExternalStringResource()");
void v8::String::VerifyExternalStringResource(
v8::String::ExternalStringResource* value) const {
i::Handle<i::String> str = Utils::OpenHandle(this);
v8::String::ExternalStringResource* expected;
if (i::StringShape(*str).IsExternalTwoByte()) {
void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
return reinterpret_cast<ExternalStringResource*>(resource);
expected = reinterpret_cast<ExternalStringResource*>(resource);
} else {
return NULL;
expected = NULL;
}
CHECK_EQ(expected, value);
}
@ -2519,7 +2514,7 @@ int v8::Object::InternalFieldCount() {
}
Local<Value> v8::Object::GetInternalField(int index) {
Local<Value> v8::Object::CheckedGetInternalField(int index) {
if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
if (!ApiCheck(index < obj->GetInternalFieldCount(),
@ -2528,7 +2523,12 @@ Local<Value> v8::Object::GetInternalField(int index) {
return Local<Value>();
}
i::Handle<i::Object> value(obj->GetInternalField(index));
return Utils::ToLocal(value);
Local<Value> result = Utils::ToLocal(value);
#ifdef DEBUG
Local<Value> unchecked = UncheckedGetInternalField(index);
ASSERT(unchecked.IsEmpty() || (unchecked == result));
#endif
return result;
}
@ -2546,41 +2546,8 @@ void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
}
void* v8::Object::GetPointerFromInternalField(int index) {
i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
i::Object* pointer = obj->GetInternalField(index);
if (pointer->IsSmi()) {
// Fast case, aligned native pointer.
return pointer;
}
// Read from uninitialized field.
if (!pointer->IsProxy()) {
// Play safe even if it's something unexpected.
ASSERT(pointer->IsUndefined());
return NULL;
}
// Unaligned native pointer.
return reinterpret_cast<void*>(i::Proxy::cast(pointer)->proxy());
}
void v8::Object::SetPointerInInternalField(int index, void* value) {
i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
i::Object* as_object = reinterpret_cast<i::Object*>(value);
if (as_object->IsSmi()) {
// Aligned pointer, store as is.
obj->SetInternalField(index, as_object);
} else {
// Currently internal fields are used by DOM wrappers which only
// get garbage collected by the mark-sweep collector, so we
// pretenure the proxy.
HandleScope scope;
i::Handle<i::Proxy> proxy =
i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
if (!proxy.is_null()) obj->SetInternalField(index, *proxy);
}
SetInternalField(index, External::Wrap(value));
}
@ -2838,8 +2805,6 @@ static void* ExternalValueImpl(i::Handle<i::Object> obj) {
static const intptr_t kAlignedPointerMask = 3;
static const int kAlignedPointerShift = 2;
Local<Value> v8::External::Wrap(void* data) {
STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
@ -2849,7 +2814,7 @@ Local<Value> v8::External::Wrap(void* data) {
if ((reinterpret_cast<intptr_t>(data) & kAlignedPointerMask) == 0) {
uintptr_t data_ptr = reinterpret_cast<uintptr_t>(data);
intptr_t data_value =
static_cast<intptr_t>(data_ptr >> kAlignedPointerShift);
static_cast<intptr_t>(data_ptr >> i::Internals::kAlignedPointerShift);
STATIC_ASSERT(sizeof(data_ptr) == sizeof(data_value));
if (i::Smi::IsIntptrValid(data_value)) {
i::Handle<i::Object> obj(i::Smi::FromIntptr(data_value));
@ -2860,16 +2825,22 @@ Local<Value> v8::External::Wrap(void* data) {
}
void* v8::External::Unwrap(v8::Handle<v8::Value> value) {
void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
if (IsDeadCheck("v8::External::Unwrap()")) return 0;
i::Handle<i::Object> obj = Utils::OpenHandle(*value);
i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
void* result;
if (obj->IsSmi()) {
// The external value was an aligned pointer.
uintptr_t result = static_cast<uintptr_t>(
i::Smi::cast(*obj)->value()) << kAlignedPointerShift;
return reinterpret_cast<void*>(result);
uintptr_t value = static_cast<uintptr_t>(
i::Smi::cast(*obj)->value()) << i::Internals::kAlignedPointerShift;
result = reinterpret_cast<void*>(value);
} else if (obj->IsProxy()) {
result = ExternalValueImpl(obj);
} else {
result = NULL;
}
return ExternalValueImpl(obj);
ASSERT_EQ(result, QuickUnwrap(wrapper));
return result;
}
@ -3731,19 +3702,17 @@ char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
void HandleScopeImplementer::Iterate(
ObjectVisitor* v,
List<void**>* blocks,
List<i::Object**>* blocks,
v8::ImplementationUtilities::HandleScopeData* handle_data) {
// Iterate over all handles in the blocks except for the last.
for (int i = blocks->length() - 2; i >= 0; --i) {
Object** block =
reinterpret_cast<Object**>(blocks->at(i));
Object** block = blocks->at(i);
v->VisitPointers(block, &block[kHandleBlockSize]);
}
// Iterate over live handles in the last block (if any).
if (!blocks->is_empty()) {
v->VisitPointers(reinterpret_cast<Object**>(blocks->last()),
reinterpret_cast<Object**>(handle_data->next));
v->VisitPointers(blocks->last(), handle_data->next);
}
}
@ -3758,7 +3727,7 @@ void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
HandleScopeImplementer* thread_local =
reinterpret_cast<HandleScopeImplementer*>(storage);
List<void**>* blocks_of_archived_thread = thread_local->Blocks();
List<internal::Object**>* blocks_of_archived_thread = thread_local->Blocks();
v8::ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread =
&thread_local->handle_scope_data_;
Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread);

View File

@ -338,7 +338,7 @@ class HandleScopeImplementer {
static char* Iterate(v8::internal::ObjectVisitor* v, char* data);
inline void** GetSpareOrNewBlock();
inline internal::Object** GetSpareOrNewBlock();
inline void DeleteExtensions(int extensions);
inline void IncrementCallDepth() {call_depth++;}
@ -356,13 +356,13 @@ class HandleScopeImplementer {
inline Handle<Object> RestoreContext();
inline bool HasSavedContexts();
inline List<void**>* Blocks() { return &blocks; }
inline List<internal::Object**>* Blocks() { return &blocks; }
inline bool IgnoreOutOfMemory() { return ignore_out_of_memory; }
inline void SetIgnoreOutOfMemory(bool value) { ignore_out_of_memory = value; }
private:
List<void**> blocks;
List<internal::Object**> blocks;
Object** spare;
int call_depth;
// Used as a stack to keep track of entered contexts.
@ -374,7 +374,7 @@ class HandleScopeImplementer {
v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
static void Iterate(ObjectVisitor* v,
List<void**>* blocks,
List<internal::Object**>* blocks,
v8::ImplementationUtilities::HandleScopeData* handle_data);
char* RestoreThreadHelper(char* from);
char* ArchiveThreadHelper(char* to);
@ -420,10 +420,10 @@ Handle<Object> HandleScopeImplementer::LastEnteredContext() {
// If there's a spare block, use it for growing the current scope.
void** HandleScopeImplementer::GetSpareOrNewBlock() {
void** block = (spare != NULL) ?
reinterpret_cast<void**>(spare) :
NewArray<void*>(kHandleBlockSize);
internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
internal::Object** block = (spare != NULL) ?
spare :
NewArray<internal::Object*>(kHandleBlockSize);
spare = NULL;
return block;
}
@ -435,18 +435,18 @@ void HandleScopeImplementer::DeleteExtensions(int extensions) {
spare = NULL;
}
for (int i = extensions; i > 1; --i) {
void** block = blocks.RemoveLast();
internal::Object** block = blocks.RemoveLast();
#ifdef DEBUG
v8::ImplementationUtilities::ZapHandleRange(block,
&block[kHandleBlockSize]);
#endif
DeleteArray(block);
}
spare = reinterpret_cast<Object**>(blocks.RemoveLast());
spare = blocks.RemoveLast();
#ifdef DEBUG
v8::ImplementationUtilities::ZapHandleRange(
reinterpret_cast<void**>(spare),
reinterpret_cast<void**>(&spare[kHandleBlockSize]));
spare,
&spare[kHandleBlockSize]);
#endif
}

View File

@ -60,7 +60,7 @@ class ImplementationUtilities {
static HandleScopeData* CurrentHandleScope();
#ifdef DEBUG
static void ZapHandleRange(void** begin, void** end);
static void ZapHandleRange(internal::Object** begin, internal::Object** end);
#endif
};

View File

@ -134,17 +134,6 @@ const intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
const intptr_t kPointerAlignment = (1 << kPointerSizeLog2);
const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
// Tag information for HeapObject.
const int kHeapObjectTag = 1;
const int kHeapObjectTagSize = 2;
const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
// Tag information for Smi.
const int kSmiTag = 0;
const int kSmiTagSize = 1;
const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
// Tag information for Failure.
const int kFailureTag = 3;
@ -429,9 +418,6 @@ enum StateTag {
#define HAS_FAILURE_TAG(value) \
((reinterpret_cast<intptr_t>(value) & kFailureTagMask) == kFailureTag)
#define HAS_HEAP_OBJECT_TAG(value) \
((reinterpret_cast<intptr_t>(value) & kHeapObjectTagMask) == kHeapObjectTag)
// OBJECT_SIZE_ALIGN returns the value aligned HeapObject size
#define OBJECT_SIZE_ALIGN(value) \
(((value) + kObjectAlignmentMask) & ~kObjectAlignmentMask)

View File

@ -53,8 +53,8 @@ int HandleScope::NumberOfHandles() {
}
void** HandleScope::Extend() {
void** result = current_.next;
Object** HandleScope::Extend() {
Object** result = current_.next;
ASSERT(result == current_.limit);
// Make sure there's at least one scope on the stack and that the
@ -68,7 +68,7 @@ void** HandleScope::Extend() {
// If there's more room in the last block, we use that. This is used
// for fast creation of scopes after scope barriers.
if (!impl->Blocks()->is_empty()) {
void** limit = &impl->Blocks()->last()[kHandleBlockSize];
Object** limit = &impl->Blocks()->last()[kHandleBlockSize];
if (current_.limit != limit) {
current_.limit = limit;
}
@ -96,10 +96,10 @@ void HandleScope::DeleteExtensions() {
}
void HandleScope::ZapRange(void** start, void** end) {
void HandleScope::ZapRange(Object** start, Object** end) {
if (start == NULL) return;
for (void** p = start; p < end; p++) {
*p = reinterpret_cast<void*>(v8::internal::kHandleZapValue);
for (Object** p = start; p < end; p++) {
*reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue;
}
}

View File

@ -121,7 +121,7 @@ class HandleScope {
// Creates a new handle with the given value.
template <typename T>
static inline T** CreateHandle(T* value) {
void** cur = current_.next;
internal::Object** cur = current_.next;
if (cur == current_.limit) cur = Extend();
// Update the current next field, set the value in the created
// handle, and return the result.
@ -164,13 +164,13 @@ class HandleScope {
}
// Extend the handle scope making room for more handles.
static void** Extend();
static internal::Object** Extend();
// Deallocates any extensions used by the current scope.
static void DeleteExtensions();
// Zaps the handles in the half-open interval [start, end).
static void ZapRange(void** start, void** end);
static void ZapRange(internal::Object** start, internal::Object** end);
friend class v8::HandleScope;
friend class v8::ImplementationUtilities;

View File

@ -2983,7 +2983,7 @@ bool Heap::LookupSymbolIfExists(String* string, String** symbol) {
#ifdef DEBUG
void Heap::ZapFromSpace() {
ASSERT(HAS_HEAP_OBJECT_TAG(kFromSpaceZapValue));
ASSERT(reinterpret_cast<Object*>(kFromSpaceZapValue)->IsHeapObject());
for (Address a = new_space_.FromSpaceLow();
a < new_space_.FromSpaceHigh();
a += kPointerSize) {

View File

@ -131,7 +131,7 @@ bool Object::IsSmi() {
bool Object::IsHeapObject() {
return HAS_HEAP_OBJECT_TAG(this);
return Internals::HasHeapObjectTag(this);
}
@ -300,6 +300,10 @@ uint32_t StringShape::full_representation_tag() {
}
STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
Internals::kFullStringRepresentationMask);
uint32_t StringShape::size_tag() {
return (type_ & kStringSizeMask);
}
@ -325,6 +329,10 @@ bool StringShape::IsExternalTwoByte() {
}
STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
Internals::kExternalTwoByteRepresentationTag);
uc32 FlatStringReader::Get(int index) {
ASSERT(0 <= index && index <= length_);
if (is_ascii_) {
@ -730,7 +738,7 @@ Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
int Smi::value() {
return static_cast<int>(reinterpret_cast<intptr_t>(this)) >> kSmiTagSize;
return Internals::SmiValue(this);
}

View File

@ -1234,6 +1234,8 @@ class HeapObject: public Object {
static const int kMapOffset = Object::kHeaderSize;
static const int kHeaderSize = kMapOffset + kPointerSize;
STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
protected:
// helpers for calling an ObjectVisitor to iterate over pointers in the
// half-open range [start, end) specified as integer offsets
@ -1664,6 +1666,8 @@ class JSObject: public HeapObject {
static const int kElementsOffset = kPropertiesOffset + kPointerSize;
static const int kHeaderSize = kElementsOffset + kPointerSize;
STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
Object* GetElementWithInterceptor(JSObject* receiver, uint32_t index);
private:
@ -2897,6 +2901,8 @@ class Map: public HeapObject {
static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
static const int kBitField2Offset = kInstanceAttributesOffset + 3;
STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
// Bit positions for bit field.
static const int kUnused = 0; // To be used for marking recently used maps.
static const int kHasNonInstancePrototype = 1;
@ -4128,6 +4134,8 @@ class ExternalString: public String {
static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
static const int kSize = kResourceOffset + kPointerSize;
STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
};
@ -4341,6 +4349,8 @@ class Proxy: public HeapObject {
static const int kProxyOffset = HeapObject::kHeaderSize;
static const int kSize = kProxyOffset + kPointerSize;
STATIC_CHECK(kProxyOffset == Internals::kProxyProxyOffset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
};

View File

@ -66,6 +66,7 @@
'DEBUG',
'_DEBUG',
'ENABLE_DISASSEMBLER',
'V8_ENABLE_CHECKS'
],
'msvs_settings': {
'VCCLCompilerTool': {

View File

@ -1394,6 +1394,7 @@
GCC_PREPROCESSOR_DEFINITIONS = (
"$(GCC_PREPROCESSOR_DEFINITIONS)",
DEBUG,
V8_ENABLE_CHECKS,
);
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
@ -1457,6 +1458,7 @@
V8_TARGET_ARCH_IA32,
V8_NATIVE_REGEXP,
DEBUG,
V8_ENABLE_CHECKS,
);
HEADER_SEARCH_PATHS = ../src;
PRODUCT_NAME = v8_shell;

View File

@ -7,7 +7,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER"
PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER;V8_ENABLE_CHECKS"
RuntimeLibrary="1"
/>
<Tool