From: Ben Noordhuis Date: Mon, 13 May 2013 01:28:40 +0000 (+0200) Subject: deps: upgrade v8 to 3.19.0 X-Git-Tag: v0.11.2~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7ee538ddfe15b2de2e325f55d208b725ec1f8ea3;p=platform%2Fupstream%2Fnodejs.git deps: upgrade v8 to 3.19.0 --- diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index e344643..d1dbb29 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,30 @@ +2013-05-10: Version 3.19.0 + + Deprecated Context::New which returns Persistent. + + Added Persistent::Reset which disposes the handle and redirects it to + point to another object. + + Deprecated WriteAscii and MayContainNonAscii. + + Exposed AssertNoAllocation to API. + + Performance and stability improvements on all platforms. + + +2013-04-30: Version 3.18.5 + + Allowed setting debugger breakpoints on CompareNilICs (issue 2660) + + Fixed beyond-heap load on x64 Crankshafted StringCharFromCode + (Chromium issue 235311) + + Change 'Parse error' to three more informative messages. + (Chromium issue 2636) + + Performance and stability improvements on all platforms. + + 2013-04-26: Version 3.18.4 Added a preliminary API for ES6 ArrayBuffers diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi index 8028b3e..0b1f397 100644 --- a/deps/v8/build/common.gypi +++ b/deps/v8/build/common.gypi @@ -454,6 +454,15 @@ }], ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \ or OS=="android"', { + 'cflags!': [ + '-O2', + '-Os', + ], + 'cflags': [ + '-fdata-sections', + '-ffunction-sections', + '-O3', + ], 'conditions': [ [ 'gcc_version==44 and clang==0', { 'cflags': [ diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index f300884..3a86e86 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -123,6 +123,7 @@ class ImplementationUtilities; class Int32; class Integer; class Isolate; +class LocalContext; class Number; class NumberObject; class Object; @@ -190,8 +191,13 @@ class UniqueId { * \param object the weak global object to be reclaimed by the garbage collector * \param parameter the value passed in when making the weak global object */ -typedef void (*WeakReferenceCallback)(Persistent object, - void* parameter); +template +class WeakReferenceCallbacks { + public: + typedef void (*Revivable)(Isolate* isolate, + Persistent* object, + P* parameter); +}; // TODO(svenpanne) Temporary definition until Chrome is in sync. typedef void (*NearDeathCallback)(Isolate* isolate, @@ -205,6 +211,9 @@ typedef void (*NearDeathCallback)(Isolate* isolate, *(static_cast(0)) = static_cast(0); \ } + +#define V8_USE_UNSAFE_HANDLES + /** * An object reference managed by the v8 garbage collector. * @@ -237,10 +246,12 @@ template class Handle { */ V8_INLINE(Handle()) : val_(0) {} +#ifdef V8_USE_UNSAFE_HANDLES /** * Creates a new handle for the specified value. */ V8_INLINE(explicit Handle(T* val)) : val_(val) {} +#endif /** * Creates a handle for the contents of the specified handle. This @@ -282,7 +293,7 @@ template class Handle { * to which they refer are identical. * The handles' references are not checked. */ - template V8_INLINE(bool operator==(Handle that) const) { + template V8_INLINE(bool operator==(const Handle that) const) { internal::Object** a = reinterpret_cast(**this); internal::Object** b = reinterpret_cast(*that); if (a == 0) return b == 0; @@ -290,6 +301,17 @@ template class Handle { return *a == *b; } +#ifndef V8_USE_UNSAFE_HANDLES + template V8_INLINE( + bool operator==(const Persistent& that) const) { + internal::Object** a = reinterpret_cast(**this); + internal::Object** b = reinterpret_cast(*that); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } +#endif + /** * Checks whether two handles are different. * Returns true if only one of the handles is empty, or if @@ -313,7 +335,46 @@ template class Handle { return Handle::Cast(*this); } +#ifndef V8_USE_UNSAFE_HANDLES + V8_INLINE(static Handle New(Isolate* isolate, Handle that)) { + return New(isolate, that.val_); + } + // TODO(dcarney): remove before cutover + V8_INLINE(static Handle New(Isolate* isolate, const Persistent& that)) { + return New(isolate, that.val_); + } + +#ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR + + private: +#endif + /** + * Creates a new handle for the specified value. + */ + V8_INLINE(explicit Handle(T* val)) : val_(val) {} +#endif + private: + template + friend class Persistent; + template + friend class Local; + friend class Arguments; + friend class String; + friend class Object; + friend class AccessorInfo; + friend Handle Undefined(Isolate* isolate); + friend Handle Null(Isolate* isolate); + friend Handle True(Isolate* isolate); + friend Handle False(Isolate* isolate); + friend class Context; + friend class InternalHandleHelper; + friend class LocalContext; + +#ifndef V8_USE_UNSAFE_HANDLES + V8_INLINE(static Handle New(Isolate* isolate, T* that)); +#endif + T* val_; }; @@ -325,6 +386,7 @@ template class Handle { * handle scope are destroyed when the handle scope is destroyed. Hence it * is not necessary to explicitly deallocate local handles. */ +// TODO(dcarney): deprecate entire class template class Local : public Handle { public: V8_INLINE(Local()); @@ -337,7 +399,12 @@ template class Local : public Handle { */ TYPE_CHECK(T, S); } + + +#ifdef V8_USE_UNSAFE_HANDLES template V8_INLINE(Local(S* that) : Handle(that)) { } +#endif + template V8_INLINE(static Local Cast(Local that)) { #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check @@ -346,6 +413,12 @@ template class Local : public Handle { #endif return Local(T::Cast(*that)); } +#ifndef V8_USE_UNSAFE_HANDLES + template V8_INLINE(Local(Handle that)) + : Handle(reinterpret_cast(*that)) { + TYPE_CHECK(T, S); + } +#endif template V8_INLINE(Local As()) { return Local::Cast(*this); @@ -358,8 +431,32 @@ template class Local : public Handle { */ V8_INLINE(static Local New(Handle that)); V8_INLINE(static Local New(Isolate* isolate, Handle that)); -}; +#ifndef V8_USE_UNSAFE_HANDLES + // TODO(dcarney): remove before cutover + V8_INLINE(static Local New(Isolate* isolate, const Persistent& that)); + +#ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR + + private: +#endif + template V8_INLINE(Local(S* that) : Handle(that)) { } +#endif + private: + template + friend class Persistent; + template + friend class Handle; + friend class Arguments; + friend class String; + friend class Object; + friend class AccessorInfo; + friend class Context; + friend class InternalHandleHelper; + friend class LocalContext; + + V8_INLINE(static Local New(Isolate* isolate, T* that)); +}; /** * An object reference that is independent of any handle scope. Where @@ -378,13 +475,38 @@ template class Local : public Handle { * different storage cells but rather two references to the same * storage cell. */ -template class Persistent : public Handle { +template class Persistent // NOLINT +#ifdef V8_USE_UNSAFE_HANDLES + : public Handle { +#else + { // NOLINT +#endif public: +#ifndef V8_USE_UNSAFE_HANDLES + V8_INLINE(Persistent()) : val_(0) { } + V8_INLINE(~Persistent()) { + // TODO(dcarney): add this back before cutover. + // Dispose(); + } + V8_INLINE(bool IsEmpty() const) { return val_ == 0; } + // TODO(dcarney): remove somehow before cutover + // The handle should either be 0, or a pointer to a live cell. + V8_INLINE(void Clear()) { val_ = 0; } + + /** + * A constructor that creates a new global cell pointing to that. In contrast + * to the copy constructor, this creates a new persistent handle which needs + * to be separately disposed. + */ + template V8_INLINE(Persistent(Isolate* isolate, Handle that)) + : val_(*New(isolate, that)) { } + +#else /** * Creates an empty persistent handle that doesn't point to any * storage cell. */ - V8_INLINE(Persistent()); + V8_INLINE(Persistent()) : Handle() { } /** * Creates a persistent handle for the same storage cell as the @@ -424,6 +546,8 @@ template class Persistent : public Handle { template explicit V8_INLINE(Persistent(Handle that)) : Handle(*that) { } +#endif + template V8_INLINE(static Persistent Cast(Persistent that)) { #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check @@ -437,16 +561,38 @@ template class Persistent : public Handle { return Persistent::Cast(*this); } - /** Deprecated. Use Isolate version instead. */ V8_DEPRECATED(static Persistent New(Handle that)); /** * Creates a new persistent handle for an existing local or persistent handle. */ + // TODO(dcarney): remove before cutover V8_INLINE(static Persistent New(Isolate* isolate, Handle that)); +#ifndef V8_USE_UNSAFE_HANDLES + // TODO(dcarney): remove before cutover + V8_INLINE(static Persistent New(Isolate* isolate, Persistent that)); +#endif - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(void Dispose()); +#ifndef V8_USE_UNSAFE_HANDLES + template V8_INLINE( + bool operator==(const Persistent& that) const) { + internal::Object** a = reinterpret_cast(**this); + internal::Object** b = reinterpret_cast(*that); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } + + template V8_INLINE(bool operator==(const Handle that) const) { + internal::Object** a = reinterpret_cast(**this); + internal::Object** b = reinterpret_cast(*that); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } +#endif + + V8_INLINE(void Dispose()); /** * Releases the storage cell referenced by this persistent handle. @@ -454,11 +600,20 @@ template class Persistent : public Handle { * This handle's reference, and any other references to the storage * cell remain and IsEmpty will still return false. */ + // TODO(dcarney): remove before cutover V8_INLINE(void Dispose(Isolate* isolate)); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(void MakeWeak(void* parameters, - WeakReferenceCallback callback)); + template + V8_INLINE(void MakeWeak( + Isolate* isolate, + P* parameters, + typename WeakReferenceCallbacks::Revivable callback)); + + template + V8_INLINE(void MakeWeak( + Isolate* isolate, + P* parameters, + typename WeakReferenceCallbacks::Revivable callback)); /** * Make the reference to this object weak. When only weak handles @@ -466,18 +621,17 @@ template class Persistent : public Handle { * callback to the given V8::NearDeathCallback function, passing * it the object reference and the given parameters. */ + // TODO(dcarney): remove before cutover V8_INLINE(void MakeWeak(Isolate* isolate, void* parameters, NearDeathCallback callback)); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(void ClearWeak()); + V8_INLINE(void ClearWeak()); - /** Clears the weak reference to this object. */ + // TODO(dcarney): remove before cutover V8_INLINE(void ClearWeak(Isolate* isolate)); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(void MarkIndependent()); + V8_INLINE(void MarkIndependent()); /** * Marks the reference to this object independent. Garbage collector is free @@ -485,10 +639,10 @@ template class Persistent : public Handle { * independent handle should not assume that it will be preceded by a global * GC prologue callback or followed by a global GC epilogue callback. */ + // TODO(dcarney): remove before cutover V8_INLINE(void MarkIndependent(Isolate* isolate)); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(void MarkPartiallyDependent()); + V8_INLINE(void MarkPartiallyDependent()); /** * Marks the reference to this object partially dependent. Partially dependent @@ -498,47 +652,103 @@ template class Persistent : public Handle { * external dependencies. This mark is automatically cleared after each * garbage collection. */ + // TODO(dcarney): remove before cutover V8_INLINE(void MarkPartiallyDependent(Isolate* isolate)); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(bool IsIndependent() const); + V8_INLINE(bool IsIndependent() const); - /** Returns true if this handle was previously marked as independent. */ + // TODO(dcarney): remove before cutover V8_INLINE(bool IsIndependent(Isolate* isolate) const); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(bool IsNearDeath() const); + V8_INLINE(bool IsNearDeath() const); /** Checks if the handle holds the only reference to an object. */ + // TODO(dcarney): remove before cutover V8_INLINE(bool IsNearDeath(Isolate* isolate) const); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(bool IsWeak() const); + V8_INLINE(bool IsWeak() const); /** Returns true if the handle's reference is weak. */ + // TODO(dcarney): remove before cutover V8_INLINE(bool IsWeak(Isolate* isolate) const); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(void SetWrapperClassId(uint16_t class_id)); + V8_INLINE(void SetWrapperClassId(uint16_t class_id)); /** * Assigns a wrapper class ID to the handle. See RetainedObjectInfo interface * description in v8-profiler.h for details. */ + // TODO(dcarney): remove before cutover V8_INLINE(void SetWrapperClassId(Isolate* isolate, uint16_t class_id)); - /** Deprecated. Use Isolate version instead. */ - V8_DEPRECATED(uint16_t WrapperClassId() const); + V8_INLINE(uint16_t WrapperClassId() const); /** * Returns the class ID previously assigned to this handle or 0 if no class ID * was previously assigned. */ + // TODO(dcarney): remove before cutover V8_INLINE(uint16_t WrapperClassId(Isolate* isolate) const); + /** + * Disposes the current contents of the handle and replaces it. + */ + V8_INLINE(void Reset(Isolate* isolate, const Handle& other)); + +#ifndef V8_USE_UNSAFE_HANDLES + +#ifndef V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT + + private: +#endif + // TODO(dcarney): make unlinkable before cutover + V8_INLINE(Persistent(const Persistent& that)) : val_(that.val_) {} + // TODO(dcarney): make unlinkable before cutover + V8_INLINE(Persistent& operator=(const Persistent& that)) { // NOLINT + this->val_ = that.val_; + return *this; + } + + public: +#ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR + + private: +#endif + // TODO(dcarney): remove before cutover + template V8_INLINE(Persistent(S* that)) : val_(that) { } + // TODO(dcarney): remove before cutover + template V8_INLINE(Persistent(Persistent that)) + : val_(*that) { + TYPE_CHECK(T, S); + } + // TODO(dcarney): remove before cutover + V8_INLINE(T* operator*() const) { return val_; } + public: +#ifndef V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW + + private: +#endif + // TODO(dcarney): remove before cutover + V8_INLINE(T* operator->() const) { return val_; } + public: +#endif + private: + template + friend class Handle; + template + friend class Local; friend class ImplementationUtilities; friend class ObjectTemplate; + friend class Context; + friend class InternalHandleHelper; + friend class LocalContext; + + V8_INLINE(static Persistent New(Isolate* isolate, T* that)); + +#ifndef V8_USE_UNSAFE_HANDLES + T* val_; +#endif }; @@ -1108,6 +1318,73 @@ class V8EXPORT Value : public Data { */ bool IsRegExp() const; + + /** + * Returns true if this value is an ArrayBuffer. + * This is an experimental feature. + */ + bool IsArrayBuffer() const; + + /** + * Returns true if this value is one of TypedArrays. + * This is an experimental feature. + */ + bool IsTypedArray() const; + + /** + * Returns true if this value is an Uint8Array. + * This is an experimental feature. + */ + bool IsUint8Array() const; + + /** + * Returns true if this value is an Uint8ClampedArray. + * This is an experimental feature. + */ + bool IsUint8ClampedArray() const; + + /** + * Returns true if this value is an Int8Array. + * This is an experimental feature. + */ + bool IsInt8Array() const; + + /** + * Returns true if this value is an Uint16Array. + * This is an experimental feature. + */ + bool IsUint16Array() const; + + /** + * Returns true if this value is an Int16Array. + * This is an experimental feature. + */ + bool IsInt16Array() const; + + /** + * Returns true if this value is an Uint32Array. + * This is an experimental feature. + */ + bool IsUint32Array() const; + + /** + * Returns true if this value is an Int32Array. + * This is an experimental feature. + */ + bool IsInt32Array() const; + + /** + * Returns true if this value is a Float32Array. + * This is an experimental feature. + */ + bool IsFloat32Array() const; + + /** + * Returns true if this value is a Float64Array. + * This is an experimental feature. + */ + bool IsFloat64Array() const; + Local ToBoolean() const; Local ToNumber() const; Local ToString() const; @@ -1185,8 +1462,7 @@ class V8EXPORT String : public Primitive { /** * This function is no longer useful. */ - // TODO(dcarney): deprecate - V8_INLINE(bool MayContainNonAscii()) const { return true; } + V8_DEPRECATED(V8_INLINE(bool MayContainNonAscii()) const) { return true; } /** * Returns whether this string contains only one byte data. @@ -1231,10 +1507,10 @@ class V8EXPORT String : public Primitive { int length = -1, int options = NO_OPTIONS) const; // ASCII characters. - int WriteAscii(char* buffer, - int start = 0, - int length = -1, - int options = NO_OPTIONS) const; + V8_DEPRECATED(int WriteAscii(char* buffer, + int start = 0, + int length = -1, + int options = NO_OPTIONS) const); // One byte characters. int WriteOneByte(uint8_t* buffer, int start = 0, @@ -2047,6 +2323,185 @@ class V8EXPORT ArrayBuffer : public Object { /** + * A base class for an instance of TypedArray series of constructors + * (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT TypedArray : public Object { + public: + /** + * Returns underlying ArrayBuffer. + */ + Local Buffer(); + /** + * Byte offset in |Buffer| + */ + size_t ByteOffset(); + /** + * Numbe of elements in this typed array. + */ + size_t Length(); + /** + * Size of typed array in bytes (e.g. for Int16Array, 2*|Length|). + */ + size_t ByteLength(); + /** + * Base address of typed array. + */ + void* BaseAddress(); + + V8_INLINE(static TypedArray* Cast(Value* obj)); + + private: + TypedArray(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint8Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Uint8Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Uint8Array* Cast(Value* obj)); + + private: + Uint8Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint8ClampedArray constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Uint8ClampedArray : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Uint8ClampedArray* Cast(Value* obj)); + + private: + Uint8ClampedArray(); + static void CheckCast(Value* obj); +}; + +/** + * An instance of Int8Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Int8Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Int8Array* Cast(Value* obj)); + + private: + Int8Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint16Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Uint16Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Uint16Array* Cast(Value* obj)); + + private: + Uint16Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Int16Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Int16Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Int16Array* Cast(Value* obj)); + + private: + Int16Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint32Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Uint32Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Uint32Array* Cast(Value* obj)); + + private: + Uint32Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Int32Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Int32Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Int32Array* Cast(Value* obj)); + + private: + Int32Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Float32Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Float32Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Float32Array* Cast(Value* obj)); + + private: + Float32Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Float64Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8EXPORT Float64Array : public TypedArray { + public: + static Local New(Handle array_buffer, + size_t byte_offset, size_t length); + V8_INLINE(static Float64Array* Cast(Value* obj)); + + private: + Float64Array(); + static void CheckCast(Value* obj); +}; + + +/** * An instance of the built-in Date constructor (ECMA-262, 15.9). */ class V8EXPORT Date : public Object { @@ -3440,6 +3895,24 @@ class V8EXPORT PersistentHandleVisitor { // NOLINT /** + * Asserts that no action is performed that could cause a handle's value + * to be modified. Useful when otherwise unsafe handle operations need to + * be performed. + */ +class V8EXPORT AssertNoGCScope { +#ifndef DEBUG + V8_INLINE(AssertNoGCScope(Isolate* isolate)) {} +#else + AssertNoGCScope(Isolate* isolate); + ~AssertNoGCScope(); + private: + Isolate* isolate_; + bool last_state_; +#endif +}; + + +/** * Container class for static utility functions. */ class V8EXPORT V8 { @@ -3909,10 +4382,11 @@ class V8EXPORT V8 { internal::Object** handle); static void DisposeGlobal(internal::Isolate* isolate, internal::Object** global_handle); + typedef WeakReferenceCallbacks::Revivable RevivableCallback; static void MakeWeak(internal::Isolate* isolate, internal::Object** global_handle, void* data, - WeakReferenceCallback weak_reference_callback, + RevivableCallback weak_reference_callback, NearDeathCallback near_death_callback); static void ClearWeak(internal::Isolate* isolate, internal::Object** global_handle); @@ -4256,7 +4730,16 @@ class V8EXPORT Context { explicit V8_INLINE(Scope(Handle context)) : context_(context) { context_->Enter(); } + V8_INLINE(Scope(Isolate* isolate, Persistent& context)) // NOLINT +#ifndef V8_USE_UNSAFE_HANDLES + : context_(Handle::New(isolate, context)) { +#else + : context_(Local::New(isolate, context)) { +#endif + context_->Enter(); + } V8_INLINE(~Scope()) { context_->Exit(); } + private: Handle context_; }; @@ -4543,7 +5026,7 @@ class Internals { static const int kJSObjectHeaderSize = 3 * kApiPointerSize; static const int kFixedArrayHeaderSize = 2 * kApiPointerSize; static const int kContextHeaderSize = 2 * kApiPointerSize; - static const int kContextEmbedderDataIndex = 56; + static const int kContextEmbedderDataIndex = 65; static const int kFullStringRepresentationMask = 0x07; static const int kStringEncodingMask = 0x4; static const int kExternalTwoByteRepresentationTag = 0x02; @@ -4695,8 +5178,30 @@ Local Local::New(Handle that) { template Local Local::New(Isolate* isolate, Handle that) { - if (that.IsEmpty()) return Local(); - T* that_ptr = *that; + return New(isolate, that.val_); +} + +#ifndef V8_USE_UNSAFE_HANDLES +template +Local Local::New(Isolate* isolate, const Persistent& that) { + return New(isolate, that.val_); +} + +template +Handle Handle::New(Isolate* isolate, T* that) { + if (that == NULL) return Handle(); + T* that_ptr = that; + internal::Object** p = reinterpret_cast(that_ptr); + return Handle(reinterpret_cast(HandleScope::CreateHandle( + reinterpret_cast(isolate), *p))); +} +#endif + + +template +Local Local::New(Isolate* isolate, T* that) { + if (that == NULL) return Local(); + T* that_ptr = that; internal::Object** p = reinterpret_cast(that_ptr); return Local(reinterpret_cast(HandleScope::CreateHandle( reinterpret_cast(isolate), *p))); @@ -4705,14 +5210,26 @@ Local Local::New(Isolate* isolate, Handle that) { template Persistent Persistent::New(Handle that) { - return New(Isolate::GetCurrent(), that); + return New(Isolate::GetCurrent(), that.val_); } template Persistent Persistent::New(Isolate* isolate, Handle that) { - if (that.IsEmpty()) return Persistent(); - internal::Object** p = reinterpret_cast(*that); + return New(Isolate::GetCurrent(), that.val_); +} + +#ifndef V8_USE_UNSAFE_HANDLES +template +Persistent Persistent::New(Isolate* isolate, Persistent that) { + return New(Isolate::GetCurrent(), that.val_); +} +#endif + +template +Persistent Persistent::New(Isolate* isolate, T* that) { + if (that == NULL) return Persistent(); + internal::Object** p = reinterpret_cast(that); return Persistent(reinterpret_cast( V8::GlobalizeReference(reinterpret_cast(isolate), p))); @@ -4730,7 +5247,7 @@ bool Persistent::IsIndependent(Isolate* isolate) const { typedef internal::Internals I; if (this->IsEmpty()) return false; if (!I::IsInitialized(isolate)) return false; - return I::GetNodeFlag(reinterpret_cast(**this), + return I::GetNodeFlag(reinterpret_cast(this->val_), I::kNodeIsIndependentShift); } @@ -4746,7 +5263,7 @@ bool Persistent::IsNearDeath(Isolate* isolate) const { typedef internal::Internals I; if (this->IsEmpty()) return false; if (!I::IsInitialized(isolate)) return false; - return I::GetNodeState(reinterpret_cast(**this)) == + return I::GetNodeState(reinterpret_cast(this->val_)) == I::kNodeStateIsNearDeathValue; } @@ -4762,7 +5279,7 @@ bool Persistent::IsWeak(Isolate* isolate) const { typedef internal::Internals I; if (this->IsEmpty()) return false; if (!I::IsInitialized(isolate)) return false; - return I::GetNodeState(reinterpret_cast(**this)) == + return I::GetNodeState(reinterpret_cast(this->val_)) == I::kNodeStateIsWeakValue; } @@ -4777,29 +5294,45 @@ template void Persistent::Dispose(Isolate* isolate) { if (this->IsEmpty()) return; V8::DisposeGlobal(reinterpret_cast(isolate), - reinterpret_cast(**this)); + reinterpret_cast(this->val_)); +#ifndef V8_USE_UNSAFE_HANDLES + val_ = 0; +#endif } template -Persistent::Persistent() : Handle() { } - -template -void Persistent::MakeWeak(void* parameters, WeakReferenceCallback callback) { - Isolate* isolate = Isolate::GetCurrent(); +template +void Persistent::MakeWeak( + Isolate* isolate, + P* parameters, + typename WeakReferenceCallbacks::Revivable callback) { + TYPE_CHECK(S, T); + typedef typename WeakReferenceCallbacks::Revivable Revivable; V8::MakeWeak(reinterpret_cast(isolate), - reinterpret_cast(**this), + reinterpret_cast(this->val_), parameters, - callback, + reinterpret_cast(callback), NULL); } + +template +template +void Persistent::MakeWeak( + Isolate* isolate, + P* parameters, + typename WeakReferenceCallbacks::Revivable callback) { + MakeWeak(isolate, parameters, callback); +} + + template void Persistent::MakeWeak(Isolate* isolate, void* parameters, NearDeathCallback callback) { V8::MakeWeak(reinterpret_cast(isolate), - reinterpret_cast(**this), + reinterpret_cast(this->val_), parameters, NULL, callback); @@ -4813,7 +5346,7 @@ void Persistent::ClearWeak() { template void Persistent::ClearWeak(Isolate* isolate) { V8::ClearWeak(reinterpret_cast(isolate), - reinterpret_cast(**this)); + reinterpret_cast(this->val_)); } template @@ -4826,7 +5359,7 @@ void Persistent::MarkIndependent(Isolate* isolate) { typedef internal::Internals I; if (this->IsEmpty()) return; if (!I::IsInitialized(isolate)) return; - I::UpdateNodeFlag(reinterpret_cast(**this), + I::UpdateNodeFlag(reinterpret_cast(this->val_), true, I::kNodeIsIndependentShift); } @@ -4841,7 +5374,7 @@ void Persistent::MarkPartiallyDependent(Isolate* isolate) { typedef internal::Internals I; if (this->IsEmpty()) return; if (!I::IsInitialized(isolate)) return; - I::UpdateNodeFlag(reinterpret_cast(**this), + I::UpdateNodeFlag(reinterpret_cast(this->val_), true, I::kNodeIsPartiallyDependentShift); } @@ -4852,11 +5385,27 @@ void Persistent::SetWrapperClassId(uint16_t class_id) { } template +void Persistent::Reset(Isolate* isolate, const Handle& other) { + Dispose(isolate); +#ifdef V8_USE_UNSAFE_HANDLES + *this = *New(isolate, other); +#else + if (other.IsEmpty()) { + this->val_ = NULL; + return; + } + internal::Object** p = reinterpret_cast(other.val_); + this->val_ = reinterpret_cast( + V8::GlobalizeReference(reinterpret_cast(isolate), p)); +#endif +} + +template void Persistent::SetWrapperClassId(Isolate* isolate, uint16_t class_id) { typedef internal::Internals I; if (this->IsEmpty()) return; if (!I::IsInitialized(isolate)) return; - internal::Object** obj = reinterpret_cast(**this); + internal::Object** obj = reinterpret_cast(this->val_); uint8_t* addr = reinterpret_cast(obj) + I::kNodeClassIdOffset; *reinterpret_cast(addr) = class_id; } @@ -4871,7 +5420,7 @@ uint16_t Persistent::WrapperClassId(Isolate* isolate) const { typedef internal::Internals I; if (this->IsEmpty()) return 0; if (!I::IsInitialized(isolate)) return 0; - internal::Object** obj = reinterpret_cast(**this); + internal::Object** obj = reinterpret_cast(this->val_); uint8_t* addr = reinterpret_cast(obj) + I::kNodeClassIdOffset; return *reinterpret_cast(addr); } @@ -5224,6 +5773,78 @@ ArrayBuffer* ArrayBuffer::Cast(v8::Value* value) { } +TypedArray* TypedArray::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Uint8Array* Uint8Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Int8Array* Int8Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Uint16Array* Uint16Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Int16Array* Int16Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Uint32Array* Uint32Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Int32Array* Int32Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Float32Array* Float32Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + +Float64Array* Float64Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast(value); +} + + Function* Function::Cast(v8::Value* value) { #ifdef V8_ENABLE_CHECKS CheckCast(value); diff --git a/deps/v8/samples/lineprocessor.cc b/deps/v8/samples/lineprocessor.cc index b5b6367..2ce31b4 100644 --- a/deps/v8/samples/lineprocessor.cc +++ b/deps/v8/samples/lineprocessor.cc @@ -25,6 +25,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// TODO(dcarney): remove +#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR +#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT + #include #ifdef ENABLE_DEBUGGER_SUPPORT @@ -124,7 +128,9 @@ void DispatchDebugMessages() { // "evaluate" command, because it must be executed some context. // In our sample we have only one context, so there is nothing really to // think about. - v8::Context::Scope scope(debug_message_context); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope scope(isolate, debug_message_context); v8::Debug::ProcessDebugMessages(); } @@ -136,8 +142,8 @@ int RunMain(int argc, char* argv[]) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handle_scope(isolate); - v8::Handle script_source(NULL); - v8::Handle script_name(NULL); + v8::Handle script_source; + v8::Handle script_name; int script_param_counter = 0; #ifdef ENABLE_DEBUGGER_SUPPORT @@ -209,7 +215,7 @@ int RunMain(int argc, char* argv[]) { // Create a new execution environment containing the built-in // functions - v8::Handle context = v8::Context::New(NULL, global); + v8::Handle context = v8::Context::New(isolate, NULL, global); // Enter the newly created execution environment. v8::Context::Scope context_scope(context); diff --git a/deps/v8/samples/process.cc b/deps/v8/samples/process.cc index 4dcc09a..fd3a821 100644 --- a/deps/v8/samples/process.cc +++ b/deps/v8/samples/process.cc @@ -25,6 +25,11 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// TODO(dcarney): remove this +#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR +#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT +#define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW + #include #include @@ -163,11 +168,11 @@ bool JsHttpRequestProcessor::Initialize(map* opts, // is what we need for the reference to remain after we return from // this method. That persistent handle has to be disposed in the // destructor. - context_ = Context::New(NULL, global); + context_.Reset(GetIsolate(), Context::New(GetIsolate(), NULL, global)); // Enter the new context so all the following operations take place // within it. - Context::Scope context_scope(context_); + Context::Scope context_scope(GetIsolate(), context_); // Make the options mapping available within the context if (!InstallMaps(opts, output)) @@ -250,7 +255,7 @@ bool JsHttpRequestProcessor::Process(HttpRequest* request) { // Enter this processor's context so all the remaining operations // take place there - Context::Scope context_scope(context_); + Context::Scope context_scope(GetIsolate(), context_); // Wrap the C++ request object in a JavaScript wrapper Handle request_obj = WrapRequest(request); @@ -303,7 +308,8 @@ Handle JsHttpRequestProcessor::WrapMap(map* obj) { Handle raw_template = MakeMapTemplate(GetIsolate()); map_template_ = Persistent::New(GetIsolate(), raw_template); } - Handle templ = map_template_; + Handle templ = + Local::New(GetIsolate(), map_template_); // Create an empty map wrapper. Handle result = templ->NewInstance(); @@ -410,7 +416,8 @@ Handle JsHttpRequestProcessor::WrapRequest(HttpRequest* request) { request_template_ = Persistent::New(GetIsolate(), raw_template); } - Handle templ = request_template_; + Handle templ = + Local::New(GetIsolate(), request_template_); // Create an empty http request wrapper. Handle result = templ->NewInstance(); diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc index 0b71c2c..da18cc7 100644 --- a/deps/v8/samples/shell.cc +++ b/deps/v8/samples/shell.cc @@ -25,6 +25,11 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// TODO(dcarney): remove this +#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR +#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT +#define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW + #include #include #include @@ -45,7 +50,7 @@ */ -v8::Persistent CreateShellContext(); +v8::Handle CreateShellContext(v8::Isolate* isolate); void RunShell(v8::Handle context); int RunMain(v8::Isolate* isolate, int argc, char* argv[]); bool ExecuteString(v8::Isolate* isolate, @@ -72,7 +77,7 @@ int main(int argc, char* argv[]) { int result; { v8::HandleScope handle_scope(isolate); - v8::Persistent context = CreateShellContext(); + v8::Handle context = CreateShellContext(isolate); if (context.IsEmpty()) { fprintf(stderr, "Error creating context\n"); return 1; @@ -81,7 +86,6 @@ int main(int argc, char* argv[]) { result = RunMain(isolate, argc, argv); if (run_shell) RunShell(context); context->Exit(); - context.Dispose(isolate); } v8::V8::Dispose(); return result; @@ -96,7 +100,7 @@ const char* ToCString(const v8::String::Utf8Value& value) { // Creates a new execution environment containing the built-in // functions. -v8::Persistent CreateShellContext() { +v8::Handle CreateShellContext(v8::Isolate* isolate) { // Create a template for the global object. v8::Handle global = v8::ObjectTemplate::New(); // Bind the global 'print' function to the C++ Print callback. @@ -110,7 +114,7 @@ v8::Persistent CreateShellContext() { // Bind the 'version' function global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); - return v8::Context::New(NULL, global); + return v8::Context::New(isolate, NULL, global); } diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 2b24ab0..8a6eaf4 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/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. +// TODO(dcarney): remove +#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT + #include "api.h" #include // For memcpy, strlen. @@ -625,7 +628,7 @@ i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) { void V8::MakeWeak(i::Isolate* isolate, i::Object** object, void* parameters, - WeakReferenceCallback weak_reference_callback, + RevivableCallback weak_reference_callback, NearDeathCallback near_death_callback) { ASSERT(isolate == i::Isolate::Current()); LOG_API(isolate, "MakeWeak"); @@ -2409,6 +2412,46 @@ bool Value::IsArray() const { } +bool Value::IsArrayBuffer() const { + if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsArrayBuffer()")) + return false; + return Utils::OpenHandle(this)->IsJSArrayBuffer(); +} + + +bool Value::IsTypedArray() const { + if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsArrayBuffer()")) + return false; + return Utils::OpenHandle(this)->IsJSTypedArray(); +} + + +#define TYPED_ARRAY_LIST(F) \ +F(Uint8Array, kExternalUnsignedByteArray) \ +F(Int8Array, kExternalByteArray) \ +F(Uint16Array, kExternalUnsignedShortArray) \ +F(Int16Array, kExternalShortArray) \ +F(Uint32Array, kExternalUnsignedIntArray) \ +F(Int32Array, kExternalIntArray) \ +F(Float32Array, kExternalFloatArray) \ +F(Float64Array, kExternalDoubleArray) \ +F(Uint8ClampedArray, kExternalPixelArray) + + +#define VALUE_IS_TYPED_ARRAY(TypedArray, type_const) \ + bool Value::Is##TypedArray() const { \ + if (IsDeadCheck(i::Isolate::Current(), "v8::Value::Is" #TypedArray "()")) \ + return false; \ + i::Handle obj = Utils::OpenHandle(this); \ + if (!obj->IsJSTypedArray()) return false; \ + return i::JSTypedArray::cast(*obj)->type() == type_const; \ + } + +TYPED_ARRAY_LIST(VALUE_IS_TYPED_ARRAY) + +#undef VALUE_IS_TYPED_ARRAY + + bool Value::IsObject() const { if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsObject()")) return false; return Utils::OpenHandle(this)->IsJSObject(); @@ -2755,6 +2798,32 @@ void v8::ArrayBuffer::CheckCast(Value* that) { } +void v8::TypedArray::CheckCast(Value* that) { + if (IsDeadCheck(i::Isolate::Current(), "v8::TypedArray::Cast()")) return; + i::Handle obj = Utils::OpenHandle(that); + ApiCheck(obj->IsJSTypedArray(), + "v8::TypedArray::Cast()", + "Could not convert to TypedArray"); +} + + +#define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst) \ + void v8::ApiClass::CheckCast(Value* that) { \ + if (IsDeadCheck(i::Isolate::Current(), "v8::" #ApiClass "::Cast()")) \ + return; \ + i::Handle obj = Utils::OpenHandle(that); \ + ApiCheck(obj->IsJSTypedArray() && \ + i::JSTypedArray::cast(*obj)->type() == typeConst, \ + "v8::" #ApiClass "::Cast()", \ + "Could not convert to " #ApiClass); \ + } + + +TYPED_ARRAY_LIST(CHECK_TYPED_ARRAY_CAST) + +#undef CHECK_TYPED_ARRAY_CAST + + void v8::Date::CheckCast(v8::Value* that) { i::Isolate* isolate = i::Isolate::Current(); if (IsDeadCheck(isolate, "v8::Date::Cast()")) return; @@ -3281,7 +3350,7 @@ Local v8::Object::ObjectProtoToString() { const char* postfix = "]"; int prefix_len = i::StrLength(prefix); - int str_len = str->Length(); + int str_len = str->Utf8Length(); int postfix_len = i::StrLength(postfix); int buf_len = prefix_len + str_len + postfix_len; @@ -3293,7 +3362,7 @@ Local v8::Object::ObjectProtoToString() { ptr += prefix_len; // Write real content. - str->WriteAscii(ptr, 0, str_len); + str->WriteUtf8(ptr, str_len); ptr += str_len; // Write postfix. @@ -4061,7 +4130,7 @@ bool String::IsOneByte() const { if (IsDeadCheck(str->GetIsolate(), "v8::String::IsOneByte()")) { return false; } - return str->IsOneByteConvertible(); + return str->HasOnlyOneByteChars(); } @@ -5806,6 +5875,131 @@ Local v8::ArrayBuffer::New(void* data, size_t byte_length) { } +Local v8::TypedArray::Buffer() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, "v8::TypedArray::Buffer()")) + return Local(); + i::Handle obj = Utils::OpenHandle(this); + ASSERT(obj->buffer()->IsJSArrayBuffer()); + i::Handle buffer(i::JSArrayBuffer::cast(obj->buffer())); + return Utils::ToLocal(buffer); +} + + +size_t v8::TypedArray::ByteOffset() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, "v8::TypedArray::ByteOffset()")) return 0; + i::Handle obj = Utils::OpenHandle(this); + return static_cast(obj->byte_offset()->Number()); +} + + +size_t v8::TypedArray::ByteLength() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, "v8::TypedArray::ByteLength()")) return 0; + i::Handle obj = Utils::OpenHandle(this); + return static_cast(obj->byte_length()->Number()); +} + + +size_t v8::TypedArray::Length() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, "v8::TypedArray::Length()")) return 0; + i::Handle obj = Utils::OpenHandle(this); + return static_cast(obj->length()->Number()); +} + + +void* v8::TypedArray::BaseAddress() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, "v8::TypedArray::BaseAddress()")) return NULL; + i::Handle obj = Utils::OpenHandle(this); + i::Handle buffer(i::JSArrayBuffer::cast(obj->buffer())); + void* buffer_data = buffer->backing_store(); + size_t byte_offset = static_cast(obj->byte_offset()->Number()); + return static_cast(buffer_data) + byte_offset; +} + + +template +i::Handle NewTypedArray( + i::Isolate* isolate, + Handle array_buffer, size_t byte_offset, size_t length) { + i::Handle obj = + isolate->factory()->NewJSTypedArray(array_type); + i::Handle buffer = Utils::OpenHandle(*array_buffer); + + ASSERT(byte_offset % sizeof(ElementType) == 0); + ASSERT(byte_offset + length * sizeof(ElementType) <= + static_cast(buffer->byte_length()->Number())); + + obj->set_buffer(*buffer); + + i::Handle byte_offset_object = isolate->factory()->NewNumber( + static_cast(byte_offset)); + obj->set_byte_offset(*byte_offset_object); + + i::Handle byte_length_object = isolate->factory()->NewNumber( + static_cast(length * sizeof(ElementType))); + obj->set_byte_length(*byte_length_object); + + i::Handle length_object = isolate->factory()->NewNumber( + static_cast(length)); + obj->set_length(*length_object); + + i::Handle elements = + isolate->factory()->NewExternalArray( + static_cast(length), array_type, + static_cast(buffer->backing_store()) + byte_offset); + i::Handle map = + isolate->factory()->GetElementsTransitionMap( + obj, elements_kind); + obj->set_map(*map); + obj->set_elements(*elements); + return obj; +} + + +#define TYPED_ARRAY_NEW(TypedArray, element_type, array_type, elements_kind) \ + Local TypedArray::New(Handle array_buffer, \ + size_t byte_offset, size_t length) { \ + i::Isolate* isolate = i::Isolate::Current(); \ + EnsureInitializedForIsolate(isolate, \ + "v8::" #TypedArray "::New(Handle, size_t, size_t)"); \ + LOG_API(isolate, \ + "v8::" #TypedArray "::New(Handle, size_t, size_t)"); \ + ENTER_V8(isolate); \ + i::Handle obj = \ + NewTypedArray( \ + isolate, array_buffer, byte_offset, length); \ + return Utils::ToLocal##TypedArray(obj); \ + } + + +TYPED_ARRAY_NEW(Uint8Array, uint8_t, kExternalUnsignedByteArray, + i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS) +TYPED_ARRAY_NEW(Uint8ClampedArray, uint8_t, kExternalPixelArray, + i::EXTERNAL_PIXEL_ELEMENTS) +TYPED_ARRAY_NEW(Int8Array, int8_t, kExternalByteArray, + i::EXTERNAL_BYTE_ELEMENTS) +TYPED_ARRAY_NEW(Uint16Array, uint16_t, kExternalUnsignedShortArray, + i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS) +TYPED_ARRAY_NEW(Int16Array, int16_t, kExternalShortArray, + i::EXTERNAL_SHORT_ELEMENTS) +TYPED_ARRAY_NEW(Uint32Array, uint32_t, kExternalUnsignedIntArray, + i::EXTERNAL_UNSIGNED_INT_ELEMENTS) +TYPED_ARRAY_NEW(Int32Array, int32_t, kExternalIntArray, + i::EXTERNAL_INT_ELEMENTS) +TYPED_ARRAY_NEW(Float32Array, float, kExternalFloatArray, + i::EXTERNAL_FLOAT_ELEMENTS) +TYPED_ARRAY_NEW(Float64Array, double, kExternalDoubleArray, + i::EXTERNAL_DOUBLE_ELEMENTS) + +#undef TYPED_ARRAY_NEW + + Local v8::Symbol::New(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast(isolate); EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()"); @@ -5883,6 +6077,19 @@ Local v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) { } +#ifdef DEBUG +v8::AssertNoGCScope::AssertNoGCScope(v8::Isolate* isolate) + : isolate_(isolate), + last_state_(i::EnterAllocationScope( + reinterpret_cast(isolate), false)) { +} + +v8::AssertNoGCScope::~AssertNoGCScope() { + i::ExitAllocationScope(reinterpret_cast(isolate_), last_state_); +} +#endif + + void V8::IgnoreOutOfMemoryException() { EnterIsolateIfNeeded()->set_ignore_out_of_memory(true); } @@ -6295,9 +6502,10 @@ String::AsciiValue::AsciiValue(v8::Handle obj) TryCatch try_catch; Handle str = obj->ToString(); if (str.IsEmpty()) return; - length_ = str->Length(); + length_ = str->Utf8Length(); str_ = i::NewArray(length_ + 1); - str->WriteAscii(str_); + str->WriteUtf8(str_); + ASSERT(i::String::NonAsciiStart(str_, length_) >= length_); } diff --git a/deps/v8/src/api.h b/deps/v8/src/api.h index f62541d..686abf7 100644 --- a/deps/v8/src/api.h +++ b/deps/v8/src/api.h @@ -171,6 +171,16 @@ class RegisteredExtension { V(Object, JSObject) \ V(Array, JSArray) \ V(ArrayBuffer, JSArrayBuffer) \ + V(TypedArray, JSTypedArray) \ + V(Uint8Array, JSTypedArray) \ + V(Uint8ClampedArray, JSTypedArray) \ + V(Int8Array, JSTypedArray) \ + V(Uint16Array, JSTypedArray) \ + V(Int16Array, JSTypedArray) \ + V(Uint32Array, JSTypedArray) \ + V(Int32Array, JSTypedArray) \ + V(Float32Array, JSTypedArray) \ + V(Float64Array, JSTypedArray) \ V(String, String) \ V(Symbol, Symbol) \ V(Script, Object) \ @@ -208,6 +218,28 @@ class Utils { v8::internal::Handle obj); static inline Local ToLocal( v8::internal::Handle obj); + + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocalUint8Array( + v8::internal::Handle obj); + static inline Local ToLocalUint8ClampedArray( + v8::internal::Handle obj); + static inline Local ToLocalInt8Array( + v8::internal::Handle obj); + static inline Local ToLocalUint16Array( + v8::internal::Handle obj); + static inline Local ToLocalInt16Array( + v8::internal::Handle obj); + static inline Local ToLocalUint32Array( + v8::internal::Handle obj); + static inline Local ToLocalInt32Array( + v8::internal::Handle obj); + static inline Local ToLocalFloat32Array( + v8::internal::Handle obj); + static inline Local ToLocalFloat64Array( + v8::internal::Handle obj); + static inline Local MessageToLocal( v8::internal::Handle obj); static inline Local StackTraceToLocal( @@ -262,14 +294,34 @@ v8::internal::Handle v8::internal::Handle::EscapeFrom( } +class InternalHandleHelper { + public: + template + static inline Local Convert(v8::internal::Handle obj) { + return Local(reinterpret_cast(obj.location())); + } +}; + + // Implementations of ToLocal #define MAKE_TO_LOCAL(Name, From, To) \ Local Utils::Name(v8::internal::Handle obj) { \ ASSERT(obj.is_null() || !obj->IsTheHole()); \ - return Local(reinterpret_cast(obj.location())); \ + return InternalHandleHelper::Convert(obj); \ } + +#define MAKE_TO_LOCAL_TYPED_ARRAY(TypedArray, typeConst) \ + Local Utils::ToLocal##TypedArray( \ + v8::internal::Handle obj) { \ + ASSERT(obj.is_null() || !obj->IsTheHole()); \ + ASSERT(obj->type() == typeConst); \ + return InternalHandleHelper:: \ + Convert(obj); \ + } + + MAKE_TO_LOCAL(ToLocal, Context, Context) MAKE_TO_LOCAL(ToLocal, Object, Value) MAKE_TO_LOCAL(ToLocal, JSFunction, Function) @@ -279,6 +331,18 @@ MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp) MAKE_TO_LOCAL(ToLocal, JSObject, Object) MAKE_TO_LOCAL(ToLocal, JSArray, Array) MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer) +MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray) + +MAKE_TO_LOCAL_TYPED_ARRAY(Uint8Array, kExternalUnsignedByteArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Uint8ClampedArray, kExternalPixelArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Int8Array, kExternalByteArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Uint16Array, kExternalUnsignedShortArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Int16Array, kExternalShortArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Uint32Array, kExternalUnsignedIntArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Int32Array, kExternalIntArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Float32Array, kExternalFloatArray) +MAKE_TO_LOCAL_TYPED_ARRAY(Float64Array, kExternalDoubleArray) + MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate) MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate) MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature) @@ -293,6 +357,7 @@ MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32) MAKE_TO_LOCAL(ExternalToLocal, JSObject, External) MAKE_TO_LOCAL(ToLocal, DeclaredAccessorDescriptor, DeclaredAccessorDescriptor) +#undef MAKE_TO_LOCAL_TYPED_ARRAY #undef MAKE_TO_LOCAL diff --git a/deps/v8/src/arguments.h b/deps/v8/src/arguments.h index f8fb00c..1423d56 100644 --- a/deps/v8/src/arguments.h +++ b/deps/v8/src/arguments.h @@ -115,15 +115,18 @@ class CustomArguments : public Relocatable { #define DECLARE_RUNTIME_FUNCTION(Type, Name) \ -Type Name(Arguments args, Isolate* isolate) - - -#define RUNTIME_FUNCTION(Type, Name) \ -Type Name(Arguments args, Isolate* isolate) - - -#define RUNTIME_ARGUMENTS(isolate, args) args, isolate - +Type Name(int args_length, Object** args_object, Isolate* isolate) + +#define RUNTIME_FUNCTION(Type, Name) \ +static Type __RT_impl_##Name(Arguments args, Isolate* isolate); \ +Type Name(int args_length, Object** args_object, Isolate* isolate) { \ + Arguments args(args_length, args_object); \ + return __RT_impl_##Name(args, isolate); \ +} \ +static Type __RT_impl_##Name(Arguments args, Isolate* isolate) + +#define RUNTIME_ARGUMENTS(isolate, args) \ + args.length(), args.arguments(), isolate } } // namespace v8::internal diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index cc6caca..86da76a 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -30,6 +30,7 @@ #if defined(V8_TARGET_ARCH_ARM) #include "bootstrapper.h" +#include "builtins-decls.h" #include "code-stubs.h" #include "regexp-macro-assembler.h" #include "stub-cache.h" @@ -73,6 +74,28 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( } +void LoadFieldStub::InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor) { + static Register registers[] = { r0 }; + descriptor->register_param_count_ = 1; + descriptor->register_params_ = registers; + descriptor->stack_parameter_count_ = NULL; + descriptor->deoptimization_handler_ = NULL; +} + + +void KeyedLoadFieldStub::InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor) { + static Register registers[] = { r1 }; + descriptor->register_param_count_ = 1; + descriptor->register_params_ = registers; + descriptor->stack_parameter_count_ = NULL; + descriptor->deoptimization_handler_ = NULL; +} + + void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { @@ -115,9 +138,10 @@ static void InitializeArrayConstructorDescriptor( int constant_stack_parameter_count) { // register state // r0 -- number of arguments + // r1 -- function // r2 -- type info cell with elements kind - static Register registers[] = { r2 }; - descriptor->register_param_count_ = 1; + static Register registers[] = { r1, r2 }; + descriptor->register_param_count_ = 2; if (constant_stack_parameter_count != 0) { // stack param count needs (constructor pointer, and single argument) descriptor->stack_parameter_count_ = &r0; @@ -3776,12 +3800,6 @@ Register InstanceofStub::left() { return r0; } Register InstanceofStub::right() { return r1; } -void LoadFieldStub::Generate(MacroAssembler* masm) { - StubCompiler::DoGenerateFastPropertyLoad(masm, r0, reg_, inobject_, index_); - __ Ret(); -} - - void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { // The displacement is the offset of the last parameter (if any) // relative to the frame pointer. @@ -4733,6 +4751,7 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { Handle terminal_kind_sentinel = TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), LAST_FAST_ELEMENTS_KIND); + __ JumpIfNotSmi(r3, &miss); __ cmp(r3, Operand(terminal_kind_sentinel)); __ b(gt, &miss); // Make sure the function is the Array() function @@ -5941,8 +5960,36 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime); __ bind(&allocated); // Fill the fields of the cons string. + Label skip_write_barrier, after_writing; + ExternalReference high_promotion_mode = ExternalReference:: + new_space_high_promotion_mode_active_address(masm->isolate()); + __ mov(r4, Operand(high_promotion_mode)); + __ ldr(r4, MemOperand(r4, 0)); + __ cmp(r4, Operand::Zero()); + __ b(eq, &skip_write_barrier); + __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); + __ RecordWriteField(r7, + ConsString::kFirstOffset, + r0, + r4, + kLRHasNotBeenSaved, + kDontSaveFPRegs); __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); + __ RecordWriteField(r7, + ConsString::kSecondOffset, + r1, + r4, + kLRHasNotBeenSaved, + kDontSaveFPRegs); + __ jmp(&after_writing); + + __ bind(&skip_write_barrier); + __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); + __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); + + __ bind(&after_writing); + __ mov(r0, Operand(r7)); __ IncrementCounter(counters->string_add_native(), 1, r2, r3); __ add(sp, sp, Operand(2 * kPointerSize)); @@ -6788,6 +6835,9 @@ static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { { REG(r5), REG(r0), REG(r6), EMIT_REMEMBERED_SET }, // FastNewClosureStub::Generate { REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET }, + // StringAddStub::Generate + { REG(r7), REG(r1), REG(r4), EMIT_REMEMBERED_SET }, + { REG(r7), REG(r0), REG(r4), EMIT_REMEMBERED_SET }, // Null termination. { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} }; @@ -7312,14 +7362,8 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { // Get the elements kind and case on that. __ cmp(r2, Operand(undefined_sentinel)); __ b(eq, &no_info); - __ ldr(r3, FieldMemOperand(r2, kPointerSize)); - - // There is no info if the call site went megamorphic either - // TODO(mvstanton): Really? I thought if it was the array function that - // the cell wouldn't get stamped as megamorphic. - __ cmp(r3, - Operand(TypeFeedbackCells::MegamorphicSentinel(masm->isolate()))); - __ b(eq, &no_info); + __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); + __ JumpIfNotSmi(r3, &no_info); __ SmiUntag(r3); __ jmp(&switch_ready); __ bind(&no_info); diff --git a/deps/v8/src/arm/debug-arm.cc b/deps/v8/src/arm/debug-arm.cc index 848fae2..6bfaf41 100644 --- a/deps/v8/src/arm/debug-arm.cc +++ b/deps/v8/src/arm/debug-arm.cc @@ -224,6 +224,15 @@ void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { } +void Debug::GenerateCompareNilICDebugBreak(MacroAssembler* masm) { + // Register state for CompareNil IC + // ----------- S t a t e ------------- + // -- r0 : value + // ----------------------------------- + Generate_DebugBreakCallHelper(masm, r0.bit(), 0); +} + + void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { // Calling convention for IC call (from ic-arm.cc) // ----------- S t a t e ------------- diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index 0ef4be0..0bc1f48 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -1593,7 +1593,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { : ObjectLiteral::kNoFlags; __ mov(r0, Operand(Smi::FromInt(flags))); int properties_count = constant_properties->length() / 2; - if (expr->depth() > 1) { + if ((FLAG_track_double_fields && expr->may_store_doubles()) || + expr->depth() > 1) { __ Push(r3, r2, r1, r0); __ CallRuntime(Runtime::kCreateObjectLiteral, 4); } else if (Serializer::enabled() || flags != ObjectLiteral::kFastElements || @@ -1939,11 +1940,12 @@ void FullCodeGenerator::VisitYield(Yield* expr) { Label resume; __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); __ b(ne, &resume); - __ pop(result_register()); if (expr->yield_kind() == Yield::SUSPEND) { - // TODO(wingo): Box into { value: VALUE, done: false }. + EmitReturnIteratorResult(false); + } else { + __ pop(result_register()); + EmitReturnSequence(); } - EmitReturnSequence(); __ bind(&resume); context()->Plug(result_register()); @@ -1955,18 +1957,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); __ str(r1, FieldMemOperand(result_register(), JSGeneratorObject::kContinuationOffset)); - __ pop(result_register()); - // TODO(wingo): Box into { value: VALUE, done: true }. - - // Exit all nested statements. - NestedStatement* current = nesting_stack_; - int stack_depth = 0; - int context_length = 0; - while (current != NULL) { - current = current->Exit(&stack_depth, &context_length); - } - __ Drop(stack_depth); - EmitReturnSequence(); + EmitReturnIteratorResult(true); break; } @@ -2074,6 +2065,55 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, } +void FullCodeGenerator::EmitReturnIteratorResult(bool done) { + Label gc_required; + Label allocated; + + Handle map(isolate()->native_context()->generator_result_map()); + + __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT); + + __ bind(&allocated); + __ mov(r1, Operand(map)); + __ pop(r2); + __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); + __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); + ASSERT_EQ(map->instance_size(), 5 * kPointerSize); + __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); + __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); + __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); + __ str(r2, + FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset)); + __ str(r3, + FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset)); + + // Only the value field needs a write barrier, as the other values are in the + // root set. + __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, + r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); + + if (done) { + // Exit all nested statements. + NestedStatement* current = nesting_stack_; + int stack_depth = 0; + int context_length = 0; + while (current != NULL) { + current = current->Exit(&stack_depth, &context_length); + } + __ Drop(stack_depth); + } + + EmitReturnSequence(); + + __ bind(&gc_required); + __ Push(Smi::FromInt(map->instance_size())); + __ CallRuntime(Runtime::kAllocateInNewSpace, 1); + __ ldr(context_register(), + MemOperand(fp, StandardFrameConstants::kContextOffset)); + __ jmp(&allocated); +} + + void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Literal* key = prop->key()->AsLiteral(); diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc index 893ac4e..c644be5 100644 --- a/deps/v8/src/arm/ic-arm.cc +++ b/deps/v8/src/arm/ic-arm.cc @@ -1180,6 +1180,25 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, ICMissMode miss_mode) { } +void StoreIC::GenerateSlow(MacroAssembler* masm) { + // ---------- S t a t e -------------- + // -- r0 : value + // -- r2 : key + // -- r1 : receiver + // -- lr : return address + // ----------------------------------- + + // Push receiver, key and value for runtime call. + __ Push(r1, r2, r0); + + // The slow case calls into the runtime to complete the store without causing + // an IC miss that would otherwise cause a transition to the generic stub. + ExternalReference ref = + ExternalReference(IC_Utility(kKeyedStoreIC_Slow), masm->isolate()); + __ TailCallExternalReference(ref, 3, 1); +} + + void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { // ---------- S t a t e -------------- // -- r0 : value diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 66c108d..3fe46ff 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -552,6 +552,11 @@ LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { } +LOperand* LChunkBuilder::UseConstant(HValue* value) { + return chunk_->DefineConstantOperand(HConstant::cast(value)); +} + + LOperand* LChunkBuilder::UseAny(HValue* value) { return value->IsConstant() ? chunk_->DefineConstantOperand(HConstant::cast(value)) @@ -672,7 +677,7 @@ LUnallocated* LChunkBuilder::TempRegister() { int vreg = allocator_->GetVirtualRegister(); if (!allocator_->AllocationOk()) { Abort("Out of virtual registers while trying to allocate temp register."); - return NULL; + vreg = 0; } operand->set_virtual_register(vreg); return operand; @@ -1300,8 +1305,8 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32()); - LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); - LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); + LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); + LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); return DefineAsRegister(new(zone()) LBitI(left, right)); } else { ASSERT(instr->representation().IsTagged()); @@ -1479,15 +1484,15 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32()); LOperand* left; - LOperand* right = UseOrConstant(instr->MostConstantOperand()); + LOperand* right = UseOrConstant(instr->BetterRightOperand()); LOperand* temp = NULL; if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && (instr->CheckFlag(HValue::kCanOverflow) || !right->IsConstantOperand())) { - left = UseRegister(instr->LeastConstantOperand()); + left = UseRegister(instr->BetterLeftOperand()); temp = TempRegister(); } else { - left = UseRegisterAtStart(instr->LeastConstantOperand()); + left = UseRegisterAtStart(instr->BetterLeftOperand()); } LMulI* mul = new(zone()) LMulI(left, right, temp); if (instr->CheckFlag(HValue::kCanOverflow) || @@ -1597,8 +1602,8 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { if (instr->representation().IsInteger32()) { ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32()); - LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); - LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); + LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); + LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); LAddI* add = new(zone()) LAddI(left, right); LInstruction* result = DefineAsRegister(add); if (instr->CheckFlag(HValue::kCanOverflow)) { @@ -1629,8 +1634,8 @@ LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { if (instr->representation().IsInteger32()) { ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32()); - left = UseRegisterAtStart(instr->LeastConstantOperand()); - right = UseOrConstantAtStart(instr->MostConstantOperand()); + left = UseRegisterAtStart(instr->BetterLeftOperand()); + right = UseOrConstantAtStart(instr->BetterRightOperand()); } else { ASSERT(instr->representation().IsDouble()); ASSERT(instr->left()->representation().IsDouble()); @@ -2114,8 +2119,8 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { - return DefineAsRegister( - new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object()))); + LOperand* obj = UseRegisterAtStart(instr->object()); + return DefineAsRegister(new(zone()) LLoadNamedField(obj)); } @@ -2150,12 +2155,6 @@ LInstruction* LChunkBuilder::DoLoadFunctionPrototype( } -LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { - LOperand* input = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new(zone()) LLoadElements(input)); -} - - LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( HLoadExternalArrayPointer* instr) { LOperand* input = UseRegisterAtStart(instr->value()); @@ -2319,14 +2318,25 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { : UseRegisterAtStart(instr->object()); } - LOperand* val = needs_write_barrier - ? UseTempRegister(instr->value()) - : UseRegister(instr->value()); + LOperand* val; + if (needs_write_barrier || + (FLAG_track_fields && instr->field_representation().IsSmi())) { + val = UseTempRegister(instr->value()); + } else if (FLAG_track_double_fields && + instr->field_representation().IsDouble()) { + val = UseRegisterAtStart(instr->value()); + } else { + val = UseRegister(instr->value()); + } // We need a temporary register for write barrier of the map field. LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; - return new(zone()) LStoreNamedField(obj, val, temp); + LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); + if (FLAG_track_fields && instr->field_representation().IsSmi()) { + return AssignEnvironment(result); + } + return result; } @@ -2378,7 +2388,9 @@ LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { info()->MarkAsDeferredCalling(); - LOperand* size = UseTempRegister(instr->size()); + LOperand* size = instr->size()->IsConstant() + ? UseConstant(instr->size()) + : UseTempRegister(instr->size()); LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); LAllocate* result = new(zone()) LAllocate(size, temp1, temp2); @@ -2440,7 +2452,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. - if (spill_index > LUnallocated::kMaxFixedIndex) { + if (spill_index > LUnallocated::kMaxFixedSlotIndex) { Abort("Too many spill slots needed for OSR"); spill_index = 0; } diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h index d81881e..116d576 100644 --- a/deps/v8/src/arm/lithium-arm.h +++ b/deps/v8/src/arm/lithium-arm.h @@ -122,7 +122,6 @@ class LCodeGen; V(Label) \ V(LazyBailout) \ V(LoadContextSlot) \ - V(LoadElements) \ V(LoadExternalArrayPointer) \ V(LoadFunctionPrototype) \ V(LoadGlobalCell) \ @@ -1574,18 +1573,6 @@ class LLoadFunctionPrototype: public LTemplateInstruction<1, 1, 0> { }; -class LLoadElements: public LTemplateInstruction<1, 1, 0> { - public: - explicit LLoadElements(LOperand* object) { - inputs_[0] = object; - } - - LOperand* object() { return inputs_[0]; } - - DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements") -}; - - class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> { public: explicit LLoadExternalArrayPointer(LOperand* object) { @@ -2142,6 +2129,9 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 1> { bool is_in_object() { return hydrogen()->is_in_object(); } int offset() { return hydrogen()->offset(); } Handle transition() const { return hydrogen()->transition(); } + Representation representation() const { + return hydrogen()->field_representation(); + } }; @@ -2787,6 +2777,9 @@ class LChunkBuilder BASE_EMBEDDED { MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value); MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value); + // An input operand in a constant operand. + MUST_USE_RESULT LOperand* UseConstant(HValue* value); + // An input operand in register, stack slot or a constant operand. // Will not be moved to a register even if one is freely available. MUST_USE_RESULT LOperand* UseAny(HValue* value); diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 29e01b9..3a0f476 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -91,6 +91,10 @@ void LCodeGen::FinishCode(Handle code) { prototype_maps_.at(i)->AddDependentCode( DependentCode::kPrototypeCheckGroup, code); } + for (int i = 0 ; i < transition_maps_.length(); i++) { + transition_maps_.at(i)->AddDependentCode( + DependentCode::kTransitionGroup, code); + } } @@ -1161,14 +1165,14 @@ void LCodeGen::DoModI(LModI* instr) { Register result = ToRegister(instr->result()); Label done; - if (CpuFeatures::IsSupported(SUDIV)) { - CpuFeatureScope scope(masm(), SUDIV); // Check for x % 0. - if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { - __ cmp(right, Operand::Zero()); - DeoptimizeIf(eq, instr->environment()); - } + if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { + __ cmp(right, Operand::Zero()); + DeoptimizeIf(eq, instr->environment()); + } + if (CpuFeatures::IsSupported(SUDIV)) { + CpuFeatureScope scope(masm(), SUDIV); // Check for (kMinInt % -1). if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { Label left_not_min_int; @@ -1185,12 +1189,12 @@ void LCodeGen::DoModI(LModI* instr) { __ sdiv(result, left, right); __ mls(result, result, right, left); - __ cmp(result, Operand::Zero()); - __ b(ne, &done); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { - __ cmp(left, Operand::Zero()); - DeoptimizeIf(lt, instr->environment()); + __ cmp(result, Operand::Zero()); + __ b(ne, &done); + __ cmp(left, Operand::Zero()); + DeoptimizeIf(lt, instr->environment()); } } else { Register scratch = scratch0(); @@ -1206,13 +1210,7 @@ void LCodeGen::DoModI(LModI* instr) { ASSERT(!scratch.is(right)); ASSERT(!scratch.is(result)); - Label vfp_modulo, both_positive, right_negative; - - // Check for x % 0. - if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { - __ cmp(right, Operand::Zero()); - DeoptimizeIf(eq, instr->environment()); - } + Label vfp_modulo, right_negative; __ Move(result, left); @@ -1230,7 +1228,7 @@ void LCodeGen::DoModI(LModI* instr) { __ JumpIfNotPowerOfTwoOrZeroAndNeg(right, scratch, &right_negative, - &both_positive); + &vfp_modulo); // Perform modulo operation (scratch contains right - 1). __ and_(result, scratch, Operand(left)); __ b(&done); @@ -1239,23 +1237,6 @@ void LCodeGen::DoModI(LModI* instr) { // Negate right. The sign of the divisor does not matter. __ rsb(right, right, Operand::Zero()); - __ bind(&both_positive); - const int kUnfolds = 3; - // If the right hand side is smaller than the (nonnegative) - // left hand side, the left hand side is the result. - // Else try a few subtractions of the left hand side. - __ mov(scratch, left); - for (int i = 0; i < kUnfolds; i++) { - // Check if the left hand side is less or equal than the - // the right hand side. - __ cmp(scratch, Operand(right)); - __ mov(result, scratch, LeaveCC, lt); - __ b(lt, &done); - // If not, reduce the left hand side by the right hand - // side and check again. - if (i < kUnfolds - 1) __ sub(scratch, scratch, right); - } - __ bind(&vfp_modulo); // Load the arguments in VFP registers. // The divisor value is preloaded before. Be careful that 'right' @@ -3076,13 +3057,20 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { + int offset = instr->hydrogen()->offset(); Register object = ToRegister(instr->object()); + if (instr->hydrogen()->representation().IsDouble()) { + DwVfpRegister result = ToDoubleRegister(instr->result()); + __ vldr(result, FieldMemOperand(object, offset)); + return; + } + Register result = ToRegister(instr->result()); if (instr->hydrogen()->is_in_object()) { - __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); + __ ldr(result, FieldMemOperand(object, offset)); } else { __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); - __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); + __ ldr(result, FieldMemOperand(result, offset)); } } @@ -3228,40 +3216,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { } -void LCodeGen::DoLoadElements(LLoadElements* instr) { - Register result = ToRegister(instr->result()); - Register input = ToRegister(instr->object()); - Register scratch = scratch0(); - - __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); - if (FLAG_debug_code) { - Label done, fail; - __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); - __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); - __ cmp(scratch, ip); - __ b(eq, &done); - __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); - __ cmp(scratch, ip); - __ b(eq, &done); - // |scratch| still contains |input|'s map. - __ ldr(scratch, FieldMemOperand(scratch, Map::kBitField2Offset)); - __ ubfx(scratch, scratch, Map::kElementsKindShift, - Map::kElementsKindBitCount); - __ cmp(scratch, Operand(GetInitialFastElementsKind())); - __ b(lt, &fail); - __ cmp(scratch, Operand(TERMINAL_FAST_ELEMENTS_KIND)); - __ b(le, &done); - __ cmp(scratch, Operand(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); - __ b(lt, &fail); - __ cmp(scratch, Operand(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); - __ b(le, &done); - __ bind(&fail); - __ Abort("Check for fast or external elements failed."); - __ bind(&done); - } -} - - void LCodeGen::DoLoadExternalArrayPointer( LLoadExternalArrayPointer* instr) { Register to_reg = ToRegister(instr->result()); @@ -4234,8 +4188,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { __ mov(r0, Operand(instr->arity())); __ mov(r2, Operand(instr->hydrogen()->property_cell())); - Object* cell_value = instr->hydrogen()->property_cell()->value(); - ElementsKind kind = static_cast(Smi::cast(cell_value)->value()); + ElementsKind kind = instr->hydrogen()->elements_kind(); if (instr->arity() == 0) { ArrayNoArgumentConstructorStub stub(kind); CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); @@ -4262,15 +4215,34 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { + Representation representation = instr->representation(); + Register object = ToRegister(instr->object()); - Register value = ToRegister(instr->value()); Register scratch = scratch0(); int offset = instr->offset(); - ASSERT(!object.is(value)); + Handle transition = instr->transition(); - if (!instr->transition().is_null()) { - __ mov(scratch, Operand(instr->transition())); + if (FLAG_track_fields && representation.IsSmi()) { + Register value = ToRegister(instr->value()); + __ SmiTag(value, value, SetCC); + if (!instr->hydrogen()->value()->range()->IsInSmiRange()) { + DeoptimizeIf(vs, instr->environment()); + } + } else if (FLAG_track_double_fields && representation.IsDouble()) { + ASSERT(transition.is_null()); + ASSERT(instr->is_in_object()); + ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + DwVfpRegister value = ToDoubleRegister(instr->value()); + __ vstr(value, FieldMemOperand(object, offset)); + return; + } + + if (!transition.is_null()) { + if (transition->CanBeDeprecated()) { + transition_maps_.Add(transition, info()->zone()); + } + __ mov(scratch, Operand(transition)); __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); if (instr->hydrogen()->NeedsWriteBarrierForMap()) { Register temp = ToRegister(instr->temp()); @@ -4287,6 +4259,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { } // Do the store. + Register value = ToRegister(instr->value()); + ASSERT(!object.is(value)); HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; @@ -5138,6 +5112,8 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { } else { mode = NUMBER_CANDIDATE_IS_SMI; } + } else { + mode = NUMBER_CANDIDATE_IS_SMI; } } @@ -5473,7 +5449,6 @@ void LCodeGen::DoAllocate(LAllocate* instr) { void LCodeGen::DoDeferredAllocate(LAllocate* instr) { - Register size = ToRegister(instr->size()); Register result = ToRegister(instr->result()); // TODO(3095996): Get rid of this. For now, we need to make the @@ -5482,8 +5457,16 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { __ mov(result, Operand(Smi::FromInt(0))); PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); - __ SmiTag(size, size); - __ push(size); + if (instr->size()->IsRegister()) { + Register size = ToRegister(instr->size()); + ASSERT(!size.is(result)); + __ SmiTag(size); + __ push(size); + } else { + int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); + __ Push(Smi::FromInt(size)); + } + if (instr->hydrogen()->CanAllocateInOldPointerSpace()) { CallRuntimeFromDeferred( Runtime::kAllocateInOldPointerSpace, 1, instr); @@ -5566,7 +5549,8 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { // Pick the right runtime function or stub to call. int properties_count = instr->hydrogen()->constant_properties_length() / 2; - if (instr->hydrogen()->depth() > 1) { + if ((FLAG_track_double_fields && instr->hydrogen()->may_store_doubles()) || + instr->hydrogen()->depth() > 1) { __ Push(r3, r2, r1, r0); CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); } else if (flags != ObjectLiteral::kFastElements || diff --git a/deps/v8/src/arm/lithium-codegen-arm.h b/deps/v8/src/arm/lithium-codegen-arm.h index ae175e5..294dcf2 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.h +++ b/deps/v8/src/arm/lithium-codegen-arm.h @@ -57,6 +57,7 @@ class LCodeGen BASE_EMBEDDED { deopt_jump_table_(4, info->zone()), deoptimization_literals_(8, info->zone()), prototype_maps_(0, info->zone()), + transition_maps_(0, info->zone()), inlined_function_count_(0), scope_(info->scope()), status_(UNUSED), @@ -418,6 +419,7 @@ class LCodeGen BASE_EMBEDDED { ZoneList deopt_jump_table_; ZoneList > deoptimization_literals_; ZoneList > prototype_maps_; + ZoneList > transition_maps_; int inlined_function_count_; Scope* const scope_; Status status_; diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index b7cd3db..6e0b4a7 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -1933,8 +1933,34 @@ void MacroAssembler::AllocateAsciiConsString(Register result, Register scratch1, Register scratch2, Label* gc_required) { - Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, - TAG_OBJECT); + Label allocate_new_space, install_map; + AllocationFlags flags = TAG_OBJECT; + + ExternalReference high_promotion_mode = ExternalReference:: + new_space_high_promotion_mode_active_address(isolate()); + mov(scratch1, Operand(high_promotion_mode)); + ldr(scratch1, MemOperand(scratch1, 0)); + cmp(scratch1, Operand::Zero()); + b(eq, &allocate_new_space); + + Allocate(ConsString::kSize, + result, + scratch1, + scratch2, + gc_required, + static_cast(flags | PRETENURE_OLD_POINTER_SPACE)); + + jmp(&install_map); + + bind(&allocate_new_space); + Allocate(ConsString::kSize, + result, + scratch1, + scratch2, + gc_required, + flags); + + bind(&install_map); InitializeNewString(result, length, @@ -3473,6 +3499,18 @@ void MacroAssembler::CheckPageFlag( } +void MacroAssembler::CheckMapDeprecated(Handle map, + Register scratch, + Label* if_deprecated) { + if (map->CanBeDeprecated()) { + mov(scratch, Operand(map)); + ldr(scratch, FieldMemOperand(scratch, Map::kBitField3Offset)); + tst(scratch, Operand(Smi::FromInt(Map::Deprecated::kMask))); + b(ne, if_deprecated); + } +} + + void MacroAssembler::JumpIfBlack(Register object, Register scratch0, Register scratch1, diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h index b736c8f..9027291 100644 --- a/deps/v8/src/arm/macro-assembler-arm.h +++ b/deps/v8/src/arm/macro-assembler-arm.h @@ -213,6 +213,10 @@ class MacroAssembler: public Assembler { Condition cc, Label* condition_met); + void CheckMapDeprecated(Handle map, + Register scratch, + Label* if_deprecated); + // Check if object is in new space. Jumps if the object is not in new space. // The register scratch can be object itself, but scratch will be clobbered. void JumpIfNotInNewSpace(Register object, diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc index 036fd7f..af65bc7 100644 --- a/deps/v8/src/arm/simulator-arm.cc +++ b/deps/v8/src/arm/simulator-arm.cc @@ -975,12 +975,14 @@ ReturnType Simulator::GetFromVFPRegister(int reg_index) { } -// For use in calls that take two double values, constructed either +// Runtime FP routines take up to two double arguments and zero +// or one integer arguments. All are consructed here. // from r0-r3 or d0 and d1. -void Simulator::GetFpArgs(double* x, double* y) { +void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { if (use_eabi_hardfloat()) { *x = vfp_registers_[0]; *y = vfp_registers_[1]; + *z = registers_[1]; } else { // We use a char buffer to get around the strict-aliasing rules which // otherwise allow the compiler to optimize away the copy. @@ -988,44 +990,12 @@ void Simulator::GetFpArgs(double* x, double* y) { // Registers 0 and 1 -> x. OS::MemCopy(buffer, registers_, sizeof(*x)); OS::MemCopy(x, buffer, sizeof(*x)); - // Registers 2 and 3 -> y. - OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); - OS::MemCopy(y, buffer, sizeof(*y)); - } -} - -// For use in calls that take one double value, constructed either -// from r0 and r1 or d0. -void Simulator::GetFpArgs(double* x) { - if (use_eabi_hardfloat()) { - *x = vfp_registers_[0]; - } else { - // We use a char buffer to get around the strict-aliasing rules which - // otherwise allow the compiler to optimize away the copy. - char buffer[sizeof(*x)]; - // Registers 0 and 1 -> x. - OS::MemCopy(buffer, registers_, sizeof(*x)); - OS::MemCopy(x, buffer, sizeof(*x)); - } -} - - -// For use in calls that take one double value constructed either -// from r0 and r1 or d0 and one integer value. -void Simulator::GetFpArgs(double* x, int32_t* y) { - if (use_eabi_hardfloat()) { - *x = vfp_registers_[0]; - *y = registers_[1]; - } else { - // We use a char buffer to get around the strict-aliasing rules which - // otherwise allow the compiler to optimize away the copy. - char buffer[sizeof(*x)]; - // Registers 0 and 1 -> x. - OS::MemCopy(buffer, registers_, sizeof(*x)); - OS::MemCopy(x, buffer, sizeof(*x)); - // Register 2 -> y. + // Register 2 and 3 -> y. OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); OS::MemCopy(y, buffer, sizeof(*y)); + // Register 2 -> z + memcpy(buffer, registers_ + 2, sizeof(*z)); + memcpy(z, buffer, sizeof(*z)); } } @@ -1648,10 +1618,12 @@ typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, int32_t arg3, int32_t arg4, int32_t arg5); -typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, - int32_t arg1, - int32_t arg2, - int32_t arg3); + +// These prototypes handle the four types of FP calls. +typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1); +typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); +typedef double (*SimulatorRuntimeFPCall)(double darg0); +typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0); // This signature supports direct call in to API function native callback // (refer to InvocationCallback in v8.h). @@ -1717,27 +1689,27 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { intptr_t external = reinterpret_cast(redirection->external_function()); if (fp_call) { + double dval0, dval1; // one or two double parameters + int32_t ival; // zero or one integer parameters + int64_t iresult = 0; // integer return value + double dresult = 0; // double return value + GetFpArgs(&dval0, &dval1, &ival); if (::v8::internal::FLAG_trace_sim || !stack_aligned) { - SimulatorRuntimeFPCall target = - reinterpret_cast(external); - double dval0, dval1; - int32_t ival; + SimulatorRuntimeCall generic_target = + reinterpret_cast(external); switch (redirection->type()) { case ExternalReference::BUILTIN_FP_FP_CALL: case ExternalReference::BUILTIN_COMPARE_CALL: - GetFpArgs(&dval0, &dval1); PrintF("Call to host function at %p with args %f, %f", - FUNCTION_ADDR(target), dval0, dval1); + FUNCTION_ADDR(generic_target), dval0, dval1); break; case ExternalReference::BUILTIN_FP_CALL: - GetFpArgs(&dval0); PrintF("Call to host function at %p with arg %f", - FUNCTION_ADDR(target), dval0); + FUNCTION_ADDR(generic_target), dval0); break; case ExternalReference::BUILTIN_FP_INT_CALL: - GetFpArgs(&dval0, &ival); PrintF("Call to host function at %p with args %f, %d", - FUNCTION_ADDR(target), dval0, ival); + FUNCTION_ADDR(generic_target), dval0, ival); break; default: UNREACHABLE(); @@ -1749,22 +1721,54 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { PrintF("\n"); } CHECK(stack_aligned); - if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) { + switch (redirection->type()) { + case ExternalReference::BUILTIN_COMPARE_CALL: { + SimulatorRuntimeCompareCall target = + reinterpret_cast(external); + iresult = target(dval0, dval1); + set_register(r0, static_cast(iresult)); + set_register(r1, static_cast(iresult >> 32)); + break; + } + case ExternalReference::BUILTIN_FP_FP_CALL: { + SimulatorRuntimeFPFPCall target = + reinterpret_cast(external); + dresult = target(dval0, dval1); + SetFpResult(dresult); + break; + } + case ExternalReference::BUILTIN_FP_CALL: { SimulatorRuntimeFPCall target = - reinterpret_cast(external); - double result = target(arg0, arg1, arg2, arg3); - SetFpResult(result); - } else { - SimulatorRuntimeCall target = - reinterpret_cast(external); - int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); - int32_t lo_res = static_cast(result); - int32_t hi_res = static_cast(result >> 32); - if (::v8::internal::FLAG_trace_sim) { - PrintF("Returned %08x\n", lo_res); + reinterpret_cast(external); + dresult = target(dval0); + SetFpResult(dresult); + break; + } + case ExternalReference::BUILTIN_FP_INT_CALL: { + SimulatorRuntimeFPIntCall target = + reinterpret_cast(external); + dresult = target(dval0, ival); + SetFpResult(dresult); + break; + } + default: + UNREACHABLE(); + break; + } + if (::v8::internal::FLAG_trace_sim || !stack_aligned) { + switch (redirection->type()) { + case ExternalReference::BUILTIN_COMPARE_CALL: + PrintF("Returned %08x\n", static_cast(iresult)); + break; + case ExternalReference::BUILTIN_FP_FP_CALL: + case ExternalReference::BUILTIN_FP_CALL: + case ExternalReference::BUILTIN_FP_INT_CALL: + PrintF("Returned %f\n", dresult); + break; + default: + UNREACHABLE(); + break; } - set_register(r0, lo_res); - set_register(r1, hi_res); } } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { SimulatorRuntimeDirectApiCall target = diff --git a/deps/v8/src/arm/simulator-arm.h b/deps/v8/src/arm/simulator-arm.h index 674ff42..45ae999 100644 --- a/deps/v8/src/arm/simulator-arm.h +++ b/deps/v8/src/arm/simulator-arm.h @@ -348,10 +348,8 @@ class Simulator { void* external_function, v8::internal::ExternalReference::Type type); - // For use in calls that take double value arguments. - void GetFpArgs(double* x, double* y); - void GetFpArgs(double* x); - void GetFpArgs(double* x, int32_t* y); + // Handle arguments and return value for runtime FP functions. + void GetFpArgs(double* x, double* y, int32_t* z); void SetFpResult(const double& result); void TrashCallerSaveRegisters(); diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index ddcbd62..127bf3f 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/deps/v8/src/arm/stub-cache-arm.cc @@ -315,11 +315,13 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( } -void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, - Register dst, - Register src, - bool inobject, - int index) { +void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, + Register dst, + Register src, + bool inobject, + int index, + Representation representation) { + ASSERT(!FLAG_track_double_fields || !representation.IsDouble()); int offset = index * kPointerSize; if (!inobject) { // Calculate the offset into the properties array. @@ -451,8 +453,10 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, Register value_reg, Register scratch1, Register scratch2, + Register scratch3, Label* miss_label, - Label* miss_restore_name) { + Label* miss_restore_name, + Label* slow) { // r0 : value Label exit; @@ -465,6 +469,15 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); } + int descriptor = transition->LastAdded(); + DescriptorArray* descriptors = transition->instance_descriptors(); + PropertyDetails details = descriptors->GetDetails(descriptor); + Representation representation = details.representation(); + ASSERT(!representation.IsNone()); + + // Ensure no transitions to deprecated maps are followed. + __ CheckMapDeprecated(transition, scratch1, miss_label); + // Check that we are allowed to write this. if (object->GetPrototype()->IsJSObject()) { JSObject* holder; @@ -480,7 +493,7 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, } Register holder_reg = CheckPrototypes( object, receiver_reg, Handle(holder), name_reg, - scratch1, scratch2, name, miss_restore_name); + scratch1, scratch2, name, miss_restore_name, SKIP_RECEIVER); // If no property was found, and the holder (the last object in the // prototype chain) is in slow mode, we need to do a negative lookup on the // holder. @@ -499,6 +512,30 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, } } + Register storage_reg = name_reg; + + if (FLAG_track_fields && representation.IsSmi()) { + __ JumpIfNotSmi(value_reg, miss_restore_name); + } else if (FLAG_track_double_fields && representation.IsDouble()) { + Label do_store, heap_number; + __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex); + __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow); + + __ JumpIfNotSmi(value_reg, &heap_number); + __ SmiUntag(scratch1, value_reg); + __ vmov(s0, scratch1); + __ vcvt_f64_s32(d0, s0); + __ jmp(&do_store); + + __ bind(&heap_number); + __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, + miss_restore_name, DONT_DO_SMI_CHECK); + __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); + + __ bind(&do_store); + __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); + } + // Stub never generated for non-global objects that require access // checks. ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); @@ -527,7 +564,7 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, - name_reg, + scratch2, kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, @@ -545,40 +582,60 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, if (index < 0) { // Set the property straight into the object. int offset = object->map()->instance_size() + (index * kPointerSize); - __ str(value_reg, FieldMemOperand(receiver_reg, offset)); + if (FLAG_track_double_fields && representation.IsDouble()) { + __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); + } else { + __ str(value_reg, FieldMemOperand(receiver_reg, offset)); + } + + if (!FLAG_track_fields || !representation.IsSmi()) { + // Skip updating write barrier if storing a smi. + __ JumpIfSmi(value_reg, &exit); - // Skip updating write barrier if storing a smi. - __ JumpIfSmi(value_reg, &exit); - - // Update the write barrier for the array address. - // Pass the now unused name_reg as a scratch register. - __ mov(name_reg, value_reg); - __ RecordWriteField(receiver_reg, - offset, - name_reg, - scratch1, - kLRHasNotBeenSaved, - kDontSaveFPRegs); + // Update the write barrier for the array address. + // Pass the now unused name_reg as a scratch register. + if (!FLAG_track_double_fields || !representation.IsDouble()) { + __ mov(name_reg, value_reg); + } else { + ASSERT(storage_reg.is(name_reg)); + } + __ RecordWriteField(receiver_reg, + offset, + name_reg, + scratch1, + kLRHasNotBeenSaved, + kDontSaveFPRegs); + } } else { // Write to the properties array. int offset = index * kPointerSize + FixedArray::kHeaderSize; // Get the properties array __ ldr(scratch1, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); - __ str(value_reg, FieldMemOperand(scratch1, offset)); + if (FLAG_track_double_fields && representation.IsDouble()) { + __ str(storage_reg, FieldMemOperand(scratch1, offset)); + } else { + __ str(value_reg, FieldMemOperand(scratch1, offset)); + } - // Skip updating write barrier if storing a smi. - __ JumpIfSmi(value_reg, &exit); + if (!FLAG_track_fields || !representation.IsSmi()) { + // Skip updating write barrier if storing a smi. + __ JumpIfSmi(value_reg, &exit); - // Update the write barrier for the array address. - // Ok to clobber receiver_reg and name_reg, since we return. - __ mov(name_reg, value_reg); - __ RecordWriteField(scratch1, - offset, - name_reg, - receiver_reg, - kLRHasNotBeenSaved, - kDontSaveFPRegs); + // Update the write barrier for the array address. + // Ok to clobber receiver_reg and name_reg, since we return. + if (!FLAG_track_double_fields || !representation.IsDouble()) { + __ mov(name_reg, value_reg); + } else { + ASSERT(storage_reg.is(name_reg)); + } + __ RecordWriteField(scratch1, + offset, + name_reg, + receiver_reg, + kLRHasNotBeenSaved, + kDontSaveFPRegs); + } } // Return the value (register r0). @@ -624,24 +681,63 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, // object and the number of in-object properties is not going to change. index -= object->map()->inobject_properties(); + Representation representation = lookup->representation(); + ASSERT(!representation.IsNone()); + if (FLAG_track_fields && representation.IsSmi()) { + __ JumpIfNotSmi(value_reg, miss_label); + } else if (FLAG_track_double_fields && representation.IsDouble()) { + // Load the double storage. + if (index < 0) { + int offset = object->map()->instance_size() + (index * kPointerSize); + __ ldr(scratch1, FieldMemOperand(receiver_reg, offset)); + } else { + __ ldr(scratch1, + FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); + int offset = index * kPointerSize + FixedArray::kHeaderSize; + __ ldr(scratch1, FieldMemOperand(scratch1, offset)); + } + + // Store the value into the storage. + Label do_store, heap_number; + __ JumpIfNotSmi(value_reg, &heap_number); + __ SmiUntag(scratch2, value_reg); + __ vmov(s0, scratch2); + __ vcvt_f64_s32(d0, s0); + __ jmp(&do_store); + + __ bind(&heap_number); + __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, + miss_label, DONT_DO_SMI_CHECK); + __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); + + __ bind(&do_store); + __ vstr(d0, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); + // Return the value (register r0). + ASSERT(value_reg.is(r0)); + __ Ret(); + return; + } + // TODO(verwaest): Share this code as a code stub. if (index < 0) { // Set the property straight into the object. int offset = object->map()->instance_size() + (index * kPointerSize); __ str(value_reg, FieldMemOperand(receiver_reg, offset)); - // Skip updating write barrier if storing a smi. - __ JumpIfSmi(value_reg, &exit); - - // Update the write barrier for the array address. - // Pass the now unused name_reg as a scratch register. - __ mov(name_reg, value_reg); - __ RecordWriteField(receiver_reg, - offset, - name_reg, - scratch1, - kLRHasNotBeenSaved, - kDontSaveFPRegs); + if (!FLAG_track_fields || !representation.IsSmi()) { + // Skip updating write barrier if storing a smi. + __ JumpIfSmi(value_reg, &exit); + + // Update the write barrier for the array address. + // Pass the now unused name_reg as a scratch register. + __ mov(name_reg, value_reg); + __ RecordWriteField(receiver_reg, + offset, + name_reg, + scratch1, + kLRHasNotBeenSaved, + kDontSaveFPRegs); + } } else { // Write to the properties array. int offset = index * kPointerSize + FixedArray::kHeaderSize; @@ -650,18 +746,20 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); __ str(value_reg, FieldMemOperand(scratch1, offset)); - // Skip updating write barrier if storing a smi. - __ JumpIfSmi(value_reg, &exit); - - // Update the write barrier for the array address. - // Ok to clobber receiver_reg and name_reg, since we return. - __ mov(name_reg, value_reg); - __ RecordWriteField(scratch1, - offset, - name_reg, - receiver_reg, - kLRHasNotBeenSaved, - kDontSaveFPRegs); + if (!FLAG_track_fields || !representation.IsSmi()) { + // Skip updating write barrier if storing a smi. + __ JumpIfSmi(value_reg, &exit); + + // Update the write barrier for the array address. + // Ok to clobber receiver_reg and name_reg, since we return. + __ mov(name_reg, value_reg); + __ RecordWriteField(scratch1, + offset, + name_reg, + receiver_reg, + kLRHasNotBeenSaved, + kDontSaveFPRegs); + } } // Return the value (register r0). @@ -1270,9 +1368,20 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend( void BaseLoadStubCompiler::GenerateLoadField(Register reg, Handle holder, - PropertyIndex index) { - GenerateFastPropertyLoad(masm(), r0, reg, holder, index); - __ Ret(); + PropertyIndex field, + Representation representation) { + if (!reg.is(receiver())) __ mov(receiver(), reg); + if (kind() == Code::LOAD_IC) { + LoadFieldStub stub(field.is_inobject(holder), + field.translate(holder), + representation); + GenerateTailCall(masm(), stub.GetCode(isolate())); + } else { + KeyedLoadFieldStub stub(field.is_inobject(holder), + field.translate(holder), + representation); + GenerateTailCall(masm(), stub.GetCode(isolate())); + } } @@ -1496,7 +1605,8 @@ Handle CallStubCompiler::CompileCallField(Handle object, // Do the right check and compute the holder register. Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); - GenerateFastPropertyLoad(masm(), r1, reg, holder, index); + GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), + index.translate(holder), Representation::Tagged()); GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); @@ -2907,19 +3017,25 @@ Handle BaseLoadStubCompiler::CompilePolymorphicIC( Register map_reg = scratch1(); int receiver_count = receiver_maps->length(); + int number_of_handled_maps = 0; __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); for (int current = 0; current < receiver_count; ++current) { - __ mov(ip, Operand(receiver_maps->at(current))); - __ cmp(map_reg, ip); - __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); + Handle map = receiver_maps->at(current); + if (!map->is_deprecated()) { + number_of_handled_maps++; + __ mov(ip, Operand(receiver_maps->at(current))); + __ cmp(map_reg, ip); + __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); + } } + ASSERT(number_of_handled_maps != 0); __ bind(&miss); TailCallBuiltin(masm(), MissBuiltin(kind())); // Return the generated code. InlineCacheState state = - receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; + number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; return GetICCode(kind(), type, name, state); } diff --git a/deps/v8/src/arraybuffer.js b/deps/v8/src/arraybuffer.js new file mode 100644 index 0000000..2b0c3dd --- /dev/null +++ b/deps/v8/src/arraybuffer.js @@ -0,0 +1,100 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"use strict"; + +var $ArrayBuffer = global.ArrayBuffer; + +// ------------------------------------------------------------------- + +function ArrayBufferConstructor(byteLength) { // length = 1 + if (%_IsConstructCall()) { + var l = TO_POSITIVE_INTEGER(byteLength); + %ArrayBufferInitialize(this, l); + } else { + return new $ArrayBuffer(byteLength); + } +} + +function ArrayBufferGetByteLength() { + if (!IS_ARRAYBUFFER(this)) { + throw MakeTypeError('incompatible_method_receiver', + ['ArrayBuffer.prototype.byteLength', this]); + } + return %ArrayBufferGetByteLength(this); +} + +// ES6 Draft 15.13.5.5.3 +function ArrayBufferSlice(start, end) { + if (!IS_ARRAYBUFFER(this)) { + throw MakeTypeError('incompatible_method_receiver', + ['ArrayBuffer.prototype.slice', this]); + } + + var relativeStart = TO_INTEGER(start); + var first; + if (relativeStart < 0) { + first = MathMax(this.byteLength + relativeStart, 0); + } else { + first = MathMin(relativeStart, this.byteLength); + } + var relativeEnd = IS_UNDEFINED(end) ? this.byteLength : TO_INTEGER(end); + var fin; + if (relativeEnd < 0) { + fin = MathMax(this.byteLength + relativeEnd, 0); + } else { + fin = MathMin(relativeEnd, this.byteLength); + } + + var newLen = fin - first; + // TODO(dslomov): implement inheritance + var result = new $ArrayBuffer(newLen); + + %ArrayBufferSliceImpl(this, result, first); + return result; +} + +function SetUpArrayBuffer() { + %CheckIsBootstrapping(); + + // Set up the ArrayBuffer constructor function. + %SetCode($ArrayBuffer, ArrayBufferConstructor); + %FunctionSetPrototype($ArrayBuffer, new $Object()); + + // Set up the constructor property on the ArrayBuffer prototype object. + %SetProperty($ArrayBuffer.prototype, "constructor", $ArrayBuffer, DONT_ENUM); + + InstallGetter($ArrayBuffer.prototype, "byteLength", ArrayBufferGetByteLength); + + InstallFunctions($ArrayBuffer.prototype, DONT_ENUM, $Array( + "slice", ArrayBufferSlice + )); +} + +SetUpArrayBuffer(); + + diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index fff588a..6b0c4b8 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -1203,6 +1203,13 @@ ExternalReference ExternalReference::old_data_space_allocation_limit_address( } +ExternalReference ExternalReference:: + new_space_high_promotion_mode_active_address(Isolate* isolate) { + return ExternalReference( + isolate->heap()->NewSpaceHighPromotionModeActiveAddress()); +} + + ExternalReference ExternalReference::handle_scope_level_address( Isolate* isolate) { return ExternalReference(HandleScope::current_level_address(isolate)); diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 32424cf..6abd5c5 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -757,6 +757,8 @@ class ExternalReference BASE_EMBEDDED { Isolate* isolate); static ExternalReference old_data_space_allocation_limit_address( Isolate* isolate); + static ExternalReference new_space_high_promotion_mode_active_address( + Isolate* isolate); static ExternalReference double_fp_operation(Token::Value operation, Isolate* isolate); diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index 10ae7de..9ffb00d 100644 --- a/deps/v8/src/ast.h +++ b/deps/v8/src/ast.h @@ -277,6 +277,14 @@ class SmallMapList { bool is_empty() const { return list_.is_empty(); } int length() const { return list_.length(); } + void AddMapIfMissing(Handle map, Zone* zone) { + map = Map::CurrentMapForDeprecated(map); + for (int i = 0; i < length(); ++i) { + if (at(i).is_identical_to(map)) return; + } + Add(map, zone); + } + void Add(Handle handle, Zone* zone) { list_.Add(handle.location(), zone); } @@ -1324,10 +1332,9 @@ class ObjectLiteral: public MaterializedLiteral { return constant_properties_; } ZoneList* properties() const { return properties_; } - bool fast_elements() const { return fast_elements_; } - - bool has_function() { return has_function_; } + bool may_store_doubles() const { return may_store_doubles_; } + bool has_function() const { return has_function_; } // Mark all computed expressions that are bound to a key that // is shadowed by a later occurrence of the same key. For the @@ -1354,17 +1361,20 @@ class ObjectLiteral: public MaterializedLiteral { bool is_simple, bool fast_elements, int depth, + bool may_store_doubles, bool has_function) : MaterializedLiteral(isolate, literal_index, is_simple, depth), constant_properties_(constant_properties), properties_(properties), fast_elements_(fast_elements), + may_store_doubles_(may_store_doubles), has_function_(has_function) {} private: Handle constant_properties_; ZoneList* properties_; bool fast_elements_; + bool may_store_doubles_; bool has_function_; }; @@ -2849,10 +2859,11 @@ class AstNodeFactory BASE_EMBEDDED { bool is_simple, bool fast_elements, int depth, + bool may_store_doubles, bool has_function) { ObjectLiteral* lit = new(zone_) ObjectLiteral( isolate_, constant_properties, properties, literal_index, - is_simple, fast_elements, depth, has_function); + is_simple, fast_elements, depth, may_store_doubles, has_function); VISIT_AND_RETURN(ObjectLiteral, lit) } diff --git a/deps/v8/src/atomicops_internals_x86_gcc.h b/deps/v8/src/atomicops_internals_x86_gcc.h index 6e55b50..e58d598 100644 --- a/deps/v8/src/atomicops_internals_x86_gcc.h +++ b/deps/v8/src/atomicops_internals_x86_gcc.h @@ -168,7 +168,7 @@ inline Atomic32 Release_Load(volatile const Atomic32* ptr) { return *ptr; } -#if defined(__x86_64__) +#if defined(__x86_64__) && defined(V8_HOST_ARCH_64_BIT) // 64-bit low-level operations on 64-bit platform. diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 85bf96e..b0d3a5e 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -201,7 +201,7 @@ class Genesis BASE_EMBEDDED { ElementsKind elements_kind); bool InstallNatives(); - void InstallTypedArray(const char* name); + Handle InstallTypedArray(const char* name); bool InstallExperimentalNatives(); void InstallBuiltinFunctionIds(); void InstallJSFunctionResultCaches(); @@ -979,28 +979,32 @@ bool Genesis::InitializeGlobal(Handle inner_global, // ECMA-262, section 15.10.7.1. FieldDescriptor field(heap->source_string(), JSRegExp::kSourceFieldIndex, - final); + final, + Representation::Tagged()); initial_map->AppendDescriptor(&field, witness); } { // ECMA-262, section 15.10.7.2. FieldDescriptor field(heap->global_string(), JSRegExp::kGlobalFieldIndex, - final); + final, + Representation::Tagged()); initial_map->AppendDescriptor(&field, witness); } { // ECMA-262, section 15.10.7.3. FieldDescriptor field(heap->ignore_case_string(), JSRegExp::kIgnoreCaseFieldIndex, - final); + final, + Representation::Tagged()); initial_map->AppendDescriptor(&field, witness); } { // ECMA-262, section 15.10.7.4. FieldDescriptor field(heap->multiline_string(), JSRegExp::kMultilineFieldIndex, - final); + final, + Representation::Tagged()); initial_map->AppendDescriptor(&field, witness); } { @@ -1009,7 +1013,8 @@ bool Genesis::InitializeGlobal(Handle inner_global, static_cast(DONT_ENUM | DONT_DELETE); FieldDescriptor field(heap->last_index_string(), JSRegExp::kLastIndexFieldIndex, - writable); + writable, + Representation::Tagged()); initial_map->AppendDescriptor(&field, witness); } @@ -1161,7 +1166,8 @@ bool Genesis::InitializeGlobal(Handle inner_global, map->set_instance_descriptors(*descriptors); { // length - FieldDescriptor d(*factory->length_string(), 0, DONT_ENUM); + FieldDescriptor d( + *factory->length_string(), 0, DONT_ENUM, Representation::Tagged()); map->AppendDescriptor(&d, witness); } { // callee @@ -1270,11 +1276,11 @@ bool Genesis::InitializeGlobal(Handle inner_global, } -void Genesis::InstallTypedArray(const char* name) { +Handle Genesis::InstallTypedArray(const char* name) { Handle global = Handle(native_context()->global_object()); - InstallFunction(global, name, JS_TYPED_ARRAY_TYPE, - JSTypedArray::kSize, isolate()->initial_object_prototype(), - Builtins::kIllegal, true); + return InstallFunction(global, name, JS_TYPED_ARRAY_TYPE, + JSTypedArray::kSize, isolate()->initial_object_prototype(), + Builtins::kIllegal, true); } @@ -1311,26 +1317,36 @@ void Genesis::InitializeExperimentalGlobal() { } } + if (FLAG_harmony_array_buffer) { + // -- A r r a y B u f f e r + Handle array_buffer_fun = + InstallFunction(global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE, + JSArrayBuffer::kSize, + isolate()->initial_object_prototype(), + Builtins::kIllegal, true); + native_context()->set_array_buffer_fun(*array_buffer_fun); + } + if (FLAG_harmony_typed_arrays) { - { // -- A r r a y B u f f e r - Handle array_buffer_fun = - InstallFunction(global, "__ArrayBuffer", JS_ARRAY_BUFFER_TYPE, - JSArrayBuffer::kSize, - isolate()->initial_object_prototype(), - Builtins::kIllegal, true); - native_context()->set_array_buffer_fun(*array_buffer_fun); - } - { - // -- T y p e d A r r a y s - InstallTypedArray("__Int8Array"); - InstallTypedArray("__Uint8Array"); - InstallTypedArray("__Int16Array"); - InstallTypedArray("__Uint16Array"); - InstallTypedArray("__Int32Array"); - InstallTypedArray("__Uint32Array"); - InstallTypedArray("__Float32Array"); - InstallTypedArray("__Float64Array"); - } + // -- T y p e d A r r a y s + Handle int8_fun = InstallTypedArray("Int8Array"); + native_context()->set_int8_array_fun(*int8_fun); + Handle uint8_fun = InstallTypedArray("Uint8Array"); + native_context()->set_uint8_array_fun(*uint8_fun); + Handle int16_fun = InstallTypedArray("Int16Array"); + native_context()->set_int16_array_fun(*int16_fun); + Handle uint16_fun = InstallTypedArray("Uint16Array"); + native_context()->set_uint16_array_fun(*uint16_fun); + Handle int32_fun = InstallTypedArray("Int32Array"); + native_context()->set_int32_array_fun(*int32_fun); + Handle uint32_fun = InstallTypedArray("Uint32Array"); + native_context()->set_uint32_array_fun(*uint32_fun); + Handle float_fun = InstallTypedArray("Float32Array"); + native_context()->set_float_array_fun(*float_fun); + Handle double_fun = InstallTypedArray("Float64Array"); + native_context()->set_double_array_fun(*double_fun); + Handle uint8c_fun = InstallTypedArray("Uint8ClampedArray"); + native_context()->set_uint8c_array_fun(*uint8c_fun); } if (FLAG_harmony_generators) { @@ -1371,6 +1387,40 @@ void Genesis::InitializeExperimentalGlobal() { *generator_object_prototype); native_context()->set_generator_object_prototype_map( *generator_object_prototype_map); + + // Create a map for generator result objects. + ASSERT(object_map->inobject_properties() == 0); + STATIC_ASSERT(JSGeneratorObject::kResultPropertyCount == 2); + Handle generator_result_map = factory()->CopyMap(object_map, + JSGeneratorObject::kResultPropertyCount); + ASSERT(generator_result_map->inobject_properties() == + JSGeneratorObject::kResultPropertyCount); + + Handle descriptors = factory()->NewDescriptorArray(0, + JSGeneratorObject::kResultPropertyCount); + DescriptorArray::WhitenessWitness witness(*descriptors); + generator_result_map->set_instance_descriptors(*descriptors); + + Handle value_string = factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("value")); + FieldDescriptor value_descr(*value_string, + JSGeneratorObject::kResultValuePropertyIndex, + NONE, + Representation::Tagged()); + generator_result_map->AppendDescriptor(&value_descr, witness); + + Handle done_string = factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("done")); + FieldDescriptor done_descr(*done_string, + JSGeneratorObject::kResultDonePropertyIndex, + NONE, + Representation::Tagged()); + generator_result_map->AppendDescriptor(&done_descr, witness); + + generator_result_map->set_unused_property_fields(0); + ASSERT_EQ(JSGeneratorObject::kResultSize, + generator_result_map->instance_size()); + native_context()->set_generator_result_map(*generator_result_map); } } @@ -1924,14 +1974,16 @@ bool Genesis::InstallNatives() { { FieldDescriptor index_field(heap()->index_string(), JSRegExpResult::kIndexIndex, - NONE); + NONE, + Representation::Tagged()); initial_map->AppendDescriptor(&index_field, witness); } { FieldDescriptor input_field(heap()->input_string(), JSRegExpResult::kInputIndex, - NONE); + NONE, + Representation::Tagged()); initial_map->AppendDescriptor(&input_field, witness); } @@ -1974,6 +2026,11 @@ bool Genesis::InstallExperimentalNatives() { "native object-observe.js") == 0) { if (!CompileExperimentalBuiltin(isolate(), i)) return false; } + if (FLAG_harmony_array_buffer && + strcmp(ExperimentalNatives::GetScriptName(i).start(), + "native arraybuffer.js") == 0) { + if (!CompileExperimentalBuiltin(isolate(), i)) return false; + } if (FLAG_harmony_typed_arrays && strcmp(ExperimentalNatives::GetScriptName(i).start(), "native typedarray.js") == 0) { @@ -2352,14 +2409,15 @@ void Genesis::TransferNamedProperties(Handle from, if (from->HasFastProperties()) { Handle descs = Handle(from->map()->instance_descriptors()); - for (int i = 0; i < descs->number_of_descriptors(); i++) { + for (int i = 0; i < from->map()->NumberOfOwnDescriptors(); i++) { PropertyDetails details = descs->GetDetails(i); switch (details.type()) { case FIELD: { HandleScope inner(isolate()); Handle key = Handle(descs->GetKey(i)); int index = descs->GetFieldIndex(i); - Handle value = Handle(from->FastPropertyAt(index), + ASSERT(!descs->GetDetails(i).representation().IsDouble()); + Handle value = Handle(from->RawFastPropertyAt(index), isolate()); CHECK_NOT_EMPTY_HANDLE(isolate(), JSObject::SetLocalPropertyIgnoreAttributes( @@ -2386,9 +2444,8 @@ void Genesis::TransferNamedProperties(Handle from, // Add to dictionary. Handle key = Handle(descs->GetKey(i)); Handle callbacks(descs->GetCallbacksObject(i), isolate()); - PropertyDetails d = PropertyDetails(details.attributes(), - CALLBACKS, - details.descriptor_index()); + PropertyDetails d = PropertyDetails( + details.attributes(), CALLBACKS, i + 1); JSObject::SetNormalizedProperty(to, key, callbacks, d); break; } diff --git a/deps/v8/src/builtins-decls.h b/deps/v8/src/builtins-decls.h new file mode 100644 index 0000000..beb5dd1 --- /dev/null +++ b/deps/v8/src/builtins-decls.h @@ -0,0 +1,40 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef V8_BUILTINS_DECLS_H_ +#define V8_BUILTINS_DECLS_H_ + +#include "arguments.h" + +namespace v8 { +namespace internal { + +DECLARE_RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure); + +} } // namespace v8::internal + +#endif // V8_BUILTINS_DECLS_H_ diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc index 5718180..661ee94 100644 --- a/deps/v8/src/builtins.cc +++ b/deps/v8/src/builtins.cc @@ -125,23 +125,31 @@ BUILTIN_LIST_C(DEF_ARG_TYPE) #ifdef DEBUG -#define BUILTIN(name) \ - MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ - name##ArgumentsType args, Isolate* isolate); \ - MUST_USE_RESULT static MaybeObject* Builtin_##name( \ - name##ArgumentsType args, Isolate* isolate) { \ - ASSERT(isolate == Isolate::Current()); \ - args.Verify(); \ - return Builtin_Impl_##name(args, isolate); \ - } \ - MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ +#define BUILTIN(name) \ + MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ + name##ArgumentsType args, Isolate* isolate); \ + MUST_USE_RESULT static MaybeObject* Builtin_##name( \ + int args_length, Object** args_object, Isolate* isolate) { \ + name##ArgumentsType args(args_length, args_object); \ + ASSERT(isolate == Isolate::Current()); \ + args.Verify(); \ + return Builtin_Impl_##name(args, isolate); \ + } \ + MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ name##ArgumentsType args, Isolate* isolate) #else // For release mode. -#define BUILTIN(name) \ - static MaybeObject* Builtin_##name(name##ArgumentsType args, Isolate* isolate) - +#define BUILTIN(name) \ + static MaybeObject* Builtin_impl##name( \ + name##ArgumentsType args, Isolate* isolate); \ + static MaybeObject* Builtin_##name( \ + int args_length, Object** args_object, Isolate* isolate) { \ + name##ArgumentsType args(args_length, args_object); \ + return Builtin_impl##name(args, isolate); \ + } \ + static MaybeObject* Builtin_impl##name( \ + name##ArgumentsType args, Isolate* isolate) #endif @@ -186,55 +194,58 @@ BUILTIN(EmptyFunction) { } -#define CONVERT_ARG_STUB_CALLER_ARGS(name) \ - Arguments* name = reinterpret_cast(args[0]); - - RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure) { - CONVERT_ARG_STUB_CALLER_ARGS(caller_args); - ASSERT(args.length() == 2); - Handle type_info = args.at(1); + // If we get 2 arguments then they are the stub parameters (constructor, type + // info). If we get 3, then the first one is a pointer to the arguments + // passed by the caller. + Arguments empty_args(0, NULL); + bool no_caller_args = args.length() == 2; + ASSERT(no_caller_args || args.length() == 3); + int parameters_start = no_caller_args ? 0 : 1; + Arguments* caller_args = no_caller_args + ? &empty_args + : reinterpret_cast(args[0]); + Handle constructor = args.at(parameters_start); + Handle type_info = args.at(parameters_start + 1); - JSArray* array = NULL; bool holey = false; if (caller_args->length() == 1 && (*caller_args)[0]->IsSmi()) { int value = Smi::cast((*caller_args)[0])->value(); holey = (value > 0 && value < JSObject::kInitialMaxFastElementArray); } + JSArray* array; MaybeObject* maybe_array; - if (*type_info != isolate->heap()->undefined_value()) { + if (*type_info != isolate->heap()->undefined_value() && + JSGlobalPropertyCell::cast(*type_info)->value()->IsSmi()) { JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info); - if (cell->value()->IsSmi()) { - Smi* smi = Smi::cast(cell->value()); - ElementsKind to_kind = static_cast(smi->value()); - if (holey && !IsFastHoleyElementsKind(to_kind)) { - to_kind = GetHoleyElementsKind(to_kind); - // Update the allocation site info to reflect the advice alteration. - cell->set_value(Smi::FromInt(to_kind)); - } - - AllocationSiteMode mode = AllocationSiteInfo::GetMode(to_kind); - if (mode == TRACK_ALLOCATION_SITE) { - maybe_array = isolate->heap()->AllocateEmptyJSArrayWithAllocationSite( - to_kind, type_info); - } else { - maybe_array = isolate->heap()->AllocateEmptyJSArray(to_kind); - } - if (!maybe_array->To(&array)) return maybe_array; + Smi* smi = Smi::cast(cell->value()); + ElementsKind to_kind = static_cast(smi->value()); + if (holey && !IsFastHoleyElementsKind(to_kind)) { + to_kind = GetHoleyElementsKind(to_kind); + // Update the allocation site info to reflect the advice alteration. + cell->set_value(Smi::FromInt(to_kind)); } - } - - ElementsKind kind = GetInitialFastElementsKind(); - if (holey) { - kind = GetHoleyElementsKind(kind); - } - if (array == NULL) { - maybe_array = isolate->heap()->AllocateEmptyJSArray(kind); + maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite( + *constructor, type_info); + if (!maybe_array->To(&array)) return maybe_array; + } else { + ElementsKind kind = constructor->initial_map()->elements_kind(); + ASSERT(kind == GetInitialFastElementsKind()); + maybe_array = isolate->heap()->AllocateJSObject(*constructor); if (!maybe_array->To(&array)) return maybe_array; + // We might need to transition to holey + if (holey) { + kind = GetHoleyElementsKind(kind); + maybe_array = array->TransitionElementsKind(kind); + if (maybe_array->IsFailure()) return maybe_array; + } } + maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0, + DONT_INITIALIZE_ARRAY_ELEMENTS); + if (maybe_array->IsFailure()) return maybe_array; maybe_array = ArrayConstructInitializeElements(array, caller_args); if (maybe_array->IsFailure()) return maybe_array; return array; @@ -1500,6 +1511,11 @@ static void Generate_KeyedLoadIC_NonStrictArguments(MacroAssembler* masm) { KeyedLoadIC::GenerateNonStrictArguments(masm); } +static void Generate_StoreIC_Slow(MacroAssembler* masm) { + StoreIC::GenerateSlow(masm); +} + + static void Generate_StoreIC_Initialize(MacroAssembler* masm) { StoreIC::GenerateInitialize(masm); } @@ -1617,6 +1633,11 @@ static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) { } +static void Generate_CompareNilIC_DebugBreak(MacroAssembler* masm) { + Debug::GenerateCompareNilICDebugBreak(masm); +} + + static void Generate_Return_DebugBreak(MacroAssembler* masm) { Debug::GenerateReturnDebugBreak(masm); } diff --git a/deps/v8/src/builtins.h b/deps/v8/src/builtins.h index ab77228..6fc17c4 100644 --- a/deps/v8/src/builtins.h +++ b/deps/v8/src/builtins.h @@ -124,6 +124,8 @@ enum BuiltinExtraArguments { Code::kNoExtraICState) \ V(StoreIC_Miss, BUILTIN, UNINITIALIZED, \ Code::kNoExtraICState) \ + V(StoreIC_Slow, BUILTIN, UNINITIALIZED, \ + Code::kNoExtraICState) \ V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, \ Code::kNoExtraICState) \ V(KeyedStoreIC_MissForceGeneric, BUILTIN, UNINITIALIZED, \ @@ -230,6 +232,8 @@ enum BuiltinExtraArguments { DEBUG_BREAK) \ V(KeyedStoreIC_DebugBreak, KEYED_STORE_IC, DEBUG_STUB, \ DEBUG_BREAK) \ + V(CompareNilIC_DebugBreak, COMPARE_NIL_IC, DEBUG_STUB, \ + DEBUG_BREAK) \ V(Slot_DebugBreak, BUILTIN, DEBUG_STUB, \ DEBUG_BREAK) \ V(PlainReturn_LiveEdit, BUILTIN, DEBUG_STUB, \ @@ -274,8 +278,6 @@ enum BuiltinExtraArguments { V(APPLY_PREPARE, 1) \ V(APPLY_OVERFLOW, 1) -MaybeObject* ArrayConstructor_StubFailure(Arguments args, Isolate* isolate); - class BuiltinFunctionTable; class ObjectVisitor; diff --git a/deps/v8/src/code-stubs-hydrogen.cc b/deps/v8/src/code-stubs-hydrogen.cc index b672079..31431b7 100644 --- a/deps/v8/src/code-stubs-hydrogen.cc +++ b/deps/v8/src/code-stubs-hydrogen.cc @@ -82,6 +82,24 @@ class CodeStubGraphBuilderBase : public HGraphBuilder { HContext* context() { return context_; } Isolate* isolate() { return info_.isolate(); } + class ArrayContextChecker { + public: + ArrayContextChecker(HGraphBuilder* builder, HValue* constructor, + HValue* array_function) + : checker_(builder) { + checker_.If(constructor, + array_function); + checker_.Then(); + } + + ~ArrayContextChecker() { + checker_.ElseDeopt(); + checker_.End(); + } + private: + IfBuilder checker_; + }; + private: SmartArrayPointer parameters_; HValue* arguments_length_; @@ -240,7 +258,8 @@ Handle HydrogenCodeStub::GenerateLightweightMissCode(Isolate* isolate) { GetCodeKind(), GetICState(), GetExtraICState(), - GetStubType(), -1); + GetStubType(), + GetStubFlags()); Handle new_object = factory->NewCode( desc, flags, masm.CodeObject(), NeedsImmovableCode()); return new_object; @@ -290,8 +309,7 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { checker.Then(); if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { - HValue* elements = - AddInstruction(new(zone) HLoadElements(boilerplate, NULL)); + HValue* elements = AddLoadElements(boilerplate); IfBuilder if_fixed_cow(this); if_fixed_cow.IfCompareMap(elements, factory->fixed_cow_array_map()); @@ -377,11 +395,12 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { for (int i = 0; i < size; i += kPointerSize) { HInstruction* value = - AddInstruction(new(zone) HLoadNamedField(boilerplate, true, i)); + AddInstruction(new(zone) HLoadNamedField( + boilerplate, true, Representation::Tagged(), i)); AddInstruction(new(zone) HStoreNamedField(object, factory->empty_string(), - value, - true, i)); + value, true, + Representation::Tagged(), i)); } checker.ElseDeopt(); @@ -409,6 +428,36 @@ Handle KeyedLoadFastElementStub::GenerateCode() { } +template<> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + Representation representation = casted_stub()->representation(); + HInstruction* load = AddInstruction(DoBuildLoadNamedField( + GetParameter(0), casted_stub()->is_inobject(), + representation, casted_stub()->offset())); + return load; +} + + +Handle LoadFieldStub::GenerateCode() { + return DoGenerateCode(this); +} + + +template<> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + Representation representation = casted_stub()->representation(); + HInstruction* load = AddInstruction(DoBuildLoadNamedField( + GetParameter(0), casted_stub()->is_inobject(), + representation, casted_stub()->offset())); + return load; +} + + +Handle KeyedLoadFieldStub::GenerateCode() { + return DoGenerateCode(this); +} + + template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { BuildUncheckedMonomorphicElementAccess( @@ -452,8 +501,7 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { if_builder.Else(); - HInstruction* elements = - AddInstruction(new(zone) HLoadElements(js_array, js_array)); + HInstruction* elements = AddLoadElements(js_array); HInstruction* elements_length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); @@ -470,12 +518,15 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { AddInstruction(new(zone) HStoreNamedField(js_array, factory->elements_field_string(), new_elements, true, + Representation::Tagged(), JSArray::kElementsOffset)); if_builder.End(); AddInstruction(new(zone) HStoreNamedField(js_array, factory->length_string(), - map, true, JSArray::kMapOffset)); + map, true, + Representation::Tagged(), + JSArray::kMapOffset)); return js_array; } @@ -491,6 +542,10 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { // -- Parameter 1 : type info cell // -- Parameter 0 : constructor // ----------------------------------- + HInstruction* array_function = BuildGetArrayFunction(context()); + ArrayContextChecker(this, + GetParameter(ArrayConstructorStubBase::kConstructor), + array_function); // Get the right map // Should be a constant JSArrayBuilder array_builder( @@ -510,6 +565,10 @@ Handle ArrayNoArgumentConstructorStub::GenerateCode() { template <> HValue* CodeStubGraphBuilder:: BuildCodeStub() { + HInstruction* array_function = BuildGetArrayFunction(context()); + ArrayContextChecker(this, + GetParameter(ArrayConstructorStubBase::kConstructor), + array_function); // Smi check and range check on the input arg. HValue* constant_one = graph()->GetConstant1(); HValue* constant_zero = graph()->GetConstant0(); @@ -563,6 +622,10 @@ Handle ArraySingleArgumentConstructorStub::GenerateCode() { template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { + HInstruction* array_function = BuildGetArrayFunction(context()); + ArrayContextChecker(this, + GetParameter(ArrayConstructorStubBase::kConstructor), + array_function); ElementsKind kind = casted_stub()->elements_kind(); HValue* length = GetArgumentsLength(); diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc index df9855d..aa2c821 100644 --- a/deps/v8/src/code-stubs.cc +++ b/deps/v8/src/code-stubs.cc @@ -431,7 +431,9 @@ CompareNilICStub::Types CompareNilICStub::GetPatchedICFlags( } else if (object->IsUndefined()) { types = static_cast( types | CompareNilICStub::kCompareAgainstUndefined); - } else if (object->IsUndetectableObject() || !object->IsHeapObject()) { + } else if (object->IsUndetectableObject() || + object->IsOddball() || + !object->IsHeapObject()) { types = CompareNilICStub::kFullCompare; } else if ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) != 0) { types = CompareNilICStub::kFullCompare; diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h index ea895d6..646aee2 100644 --- a/deps/v8/src/code-stubs.h +++ b/deps/v8/src/code-stubs.h @@ -87,7 +87,8 @@ namespace internal { V(ArrayConstructor) \ V(ProfileEntryHook) \ /* IC Handler stubs */ \ - V(LoadField) + V(LoadField) \ + V(KeyedLoadField) // List of code stubs only used on ARM platforms. #ifdef V8_TARGET_ARCH_ARM @@ -185,6 +186,12 @@ class CodeStub BASE_EMBEDDED { virtual Code::ExtraICState GetExtraICState() { return Code::kNoExtraICState; } + virtual Code::StubType GetStubType() { + return Code::NORMAL; + } + virtual int GetStubFlags() { + return -1; + } protected: static bool CanUseFPRegisters(); @@ -192,9 +199,6 @@ class CodeStub BASE_EMBEDDED { // Generates the assembler code for the stub. virtual Handle GenerateCode() = 0; - virtual Code::StubType GetStubType() { - return Code::NORMAL; - } // Returns whether the code generated for this stub needs to be allocated as // a fixed (non-moveable) code object. @@ -253,7 +257,6 @@ class PlatformCodeStub : public CodeStub { virtual Handle GenerateCode(); virtual Code::Kind GetCodeKind() const { return Code::STUB; } - virtual int GetStubFlags() { return -1; } protected: // Generates the assembler code for the stub. @@ -754,42 +757,108 @@ class StoreArrayLengthStub: public StoreICStub { }; -class HandlerStub: public ICStub { +class HICStub: public HydrogenCodeStub { + public: + virtual Code::Kind GetCodeKind() const { return kind(); } + virtual InlineCacheState GetICState() { return MONOMORPHIC; } + + protected: + HICStub() : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) { } + class KindBits: public BitField {}; + virtual Code::Kind kind() const = 0; +}; + + +class HandlerStub: public HICStub { public: - explicit HandlerStub(Code::Kind kind) : ICStub(kind) { } virtual Code::Kind GetCodeKind() const { return Code::STUB; } virtual int GetStubFlags() { return kind(); } + + protected: + HandlerStub() : HICStub() { } }; class LoadFieldStub: public HandlerStub { public: - LoadFieldStub(Register reg, bool inobject, int index) - : HandlerStub(Code::LOAD_IC), - reg_(reg), - inobject_(inobject), - index_(index) { } - virtual void Generate(MacroAssembler* masm); + LoadFieldStub(bool inobject, int index, Representation representation) + : HandlerStub() { + Initialize(Code::LOAD_IC, inobject, index, representation); + } + + virtual Handle GenerateCode(); + + virtual void InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor); + + Representation representation() { + if (unboxed_double()) return Representation::Double(); + return Representation::Tagged(); + } + + virtual Code::Kind kind() const { + return KindBits::decode(bit_field_); + } + + bool is_inobject() { + return InobjectBits::decode(bit_field_); + } + + int offset() { + int index = IndexBits::decode(bit_field_); + int offset = index * kPointerSize; + if (is_inobject()) return offset; + return FixedArray::kHeaderSize + offset; + } + + bool unboxed_double() { + return UnboxedDoubleBits::decode(bit_field_); + } - protected: virtual Code::StubType GetStubType() { return Code::FIELD; } + protected: + LoadFieldStub() : HandlerStub() { } + + void Initialize(Code::Kind kind, + bool inobject, + int index, + Representation representation) { + bool unboxed_double = FLAG_track_double_fields && representation.IsDouble(); + bit_field_ = KindBits::encode(kind) + | InobjectBits::encode(inobject) + | IndexBits::encode(index) + | UnboxedDoubleBits::encode(unboxed_double); + } + private: STATIC_ASSERT(KindBits::kSize == 4); - class RegisterBits: public BitField {}; - class InobjectBits: public BitField {}; - class IndexBits: public BitField {}; + class InobjectBits: public BitField {}; + class IndexBits: public BitField {}; + class UnboxedDoubleBits: public BitField {}; virtual CodeStub::Major MajorKey() { return LoadField; } - virtual int MinorKey() { - return KindBits::encode(kind()) - | RegisterBits::encode(reg_.code()) - | InobjectBits::encode(inobject_) - | IndexBits::encode(index_); + virtual int NotMissMinorKey() { return bit_field_; } + + int bit_field_; +}; + + +class KeyedLoadFieldStub: public LoadFieldStub { + public: + KeyedLoadFieldStub(bool inobject, int index, Representation representation) + : LoadFieldStub() { + Initialize(Code::KEYED_LOAD_IC, inobject, index, representation); } - Register reg_; - bool inobject_; - int index_; + virtual void InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor); + + virtual Handle GenerateCode(); + + private: + virtual CodeStub::Major MajorKey() { return KeyedLoadField; } }; @@ -1596,7 +1665,8 @@ class ArrayConstructorStubBase : public HydrogenCodeStub { static void InstallDescriptors(Isolate* isolate); // Parameters accessed via CodeStubGraphBuilder::GetParameter() - static const int kPropertyCell = 0; + static const int kConstructor = 0; + static const int kPropertyCell = 1; private: int NotMissMinorKey() { return bit_field_; } diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index dce8171..b7ff92a 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -144,7 +144,8 @@ Code::Flags CompilationInfo::flags() const { return Code::ComputeFlags(code_stub()->GetCodeKind(), code_stub()->GetICState(), code_stub()->GetExtraICState(), - Code::NORMAL, -1); + code_stub()->GetStubType(), + code_stub()->GetStubFlags()); } else { return Code::ComputeFlags(Code::OPTIMIZED_FUNCTION); } @@ -299,14 +300,14 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { // // The encoding is as a signed value, with parameters and receiver using // the negative indices and locals the non-negative ones. - const int parameter_limit = -LUnallocated::kMinFixedIndex; + const int parameter_limit = -LUnallocated::kMinFixedSlotIndex; Scope* scope = info()->scope(); if ((scope->num_parameters() + 1) > parameter_limit) { info()->set_bailout_reason("too many parameters"); return AbortOptimization(); } - const int locals_limit = LUnallocated::kMaxFixedIndex; + const int locals_limit = LUnallocated::kMaxFixedSlotIndex; if (!info()->osr_ast_id().IsNone() && scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { info()->set_bailout_reason("too many parameters/locals"); diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h index 0024e13..434b274 100644 --- a/deps/v8/src/contexts.h +++ b/deps/v8/src/contexts.h @@ -124,6 +124,15 @@ enum BindingFlags { V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \ V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \ V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \ + V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun) \ + V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \ + V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun) \ + V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun) \ + V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun) \ + V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \ + V(FLOAT_ARRAY_FUN_INDEX, JSFunction, float_array_fun) \ + V(DOUBLE_ARRAY_FUN_INDEX, JSFunction, double_array_fun) \ + V(UINT8C_ARRAY_FUN_INDEX, JSFunction, uint8c_array_fun) \ V(FUNCTION_MAP_INDEX, Map, function_map) \ V(STRICT_MODE_FUNCTION_MAP_INDEX, Map, strict_mode_function_map) \ V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \ @@ -171,6 +180,7 @@ enum BindingFlags { strict_mode_generator_function_map) \ V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \ generator_object_prototype_map) \ + V(GENERATOR_RESULT_MAP_INDEX, Map, generator_result_map) \ V(RANDOM_SEED_INDEX, ByteArray, random_seed) // JSFunctions are pairs (context, function code), sometimes also called @@ -278,6 +288,15 @@ class Context: public FixedArray { INSTANTIATE_FUN_INDEX, CONFIGURE_INSTANCE_FUN_INDEX, ARRAY_BUFFER_FUN_INDEX, + UINT8_ARRAY_FUN_INDEX, + INT8_ARRAY_FUN_INDEX, + UINT16_ARRAY_FUN_INDEX, + INT16_ARRAY_FUN_INDEX, + UINT32_ARRAY_FUN_INDEX, + INT32_ARRAY_FUN_INDEX, + FLOAT_ARRAY_FUN_INDEX, + DOUBLE_ARRAY_FUN_INDEX, + UINT8C_ARRAY_FUN_INDEX, MESSAGE_LISTENERS_INDEX, MAKE_MESSAGE_FUN_INDEX, GET_STACK_TRACE_LINE_INDEX, @@ -305,6 +324,7 @@ class Context: public FixedArray { GENERATOR_FUNCTION_MAP_INDEX, STRICT_MODE_GENERATOR_FUNCTION_MAP_INDEX, GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, + GENERATOR_RESULT_MAP_INDEX, RANDOM_SEED_INDEX, // Properties from here are treated as weak references by the full GC. diff --git a/deps/v8/src/d8-debug.cc b/deps/v8/src/d8-debug.cc index a20de43..e1d29d9 100644 --- a/deps/v8/src/d8-debug.cc +++ b/deps/v8/src/d8-debug.cc @@ -77,7 +77,7 @@ void HandleDebugEvent(DebugEvent event, // Print the event details. Handle details = - Shell::DebugMessageDetails(Handle::Cast(event_json)); + Shell::DebugMessageDetails(isolate, Handle::Cast(event_json)); if (try_catch.HasCaught()) { Shell::ReportException(isolate, &try_catch); return; @@ -114,7 +114,7 @@ void HandleDebugEvent(DebugEvent event, // Convert the debugger command to a JSON debugger request. Handle request = - Shell::DebugCommandToJSONRequest(String::New(command)); + Shell::DebugCommandToJSONRequest(isolate, String::New(command)); if (try_catch.HasCaught()) { Shell::ReportException(isolate, &try_catch); continue; @@ -146,7 +146,8 @@ void HandleDebugEvent(DebugEvent event, Handle response = Handle::Cast(response_val); // Convert the debugger response into text details and the running state. - Handle response_details = Shell::DebugMessageDetails(response); + Handle response_details = + Shell::DebugMessageDetails(isolate, response); if (try_catch.HasCaught()) { Shell::ReportException(isolate, &try_catch); continue; @@ -281,7 +282,8 @@ void RemoteDebugger::HandleMessageReceived(char* message) { // Print the event details. TryCatch try_catch; Handle details = - Shell::DebugMessageDetails(Handle::Cast(String::New(message))); + Shell::DebugMessageDetails(isolate_, + Handle::Cast(String::New(message))); if (try_catch.HasCaught()) { Shell::ReportException(isolate_, &try_catch); PrintPrompt(); @@ -310,7 +312,7 @@ void RemoteDebugger::HandleKeyboardCommand(char* command) { // Convert the debugger command to a JSON debugger request. TryCatch try_catch; Handle request = - Shell::DebugCommandToJSONRequest(String::New(command)); + Shell::DebugCommandToJSONRequest(isolate_, String::New(command)); if (try_catch.HasCaught()) { Shell::ReportException(isolate_, &try_catch); PrintPrompt(); diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc index 22ace17..1889556 100644 --- a/deps/v8/src/d8.cc +++ b/deps/v8/src/d8.cc @@ -40,6 +40,11 @@ #include #include +// TODO(dcarney): remove +#define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW +#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR +#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT + #ifdef V8_SHARED #include #endif // V8_SHARED @@ -124,8 +129,8 @@ class PerIsolateData { } #define DEFINE_STRING_GETTER(name, value) \ - static Persistent name##_string(Isolate* isolate) { \ - return Get(isolate)->name##_string_; \ + static Handle name##_string(Isolate* isolate) { \ + return Handle(*Get(isolate)->name##_string_); \ } FOR_EACH_STRING(DEFINE_STRING_GETTER) #undef DEFINE_STRING_GETTER @@ -245,7 +250,7 @@ bool Shell::ExecuteString(Isolate* isolate, } else { PerIsolateData* data = PerIsolateData::Get(isolate); Local realm = - Local::New(data->realms_[data->realm_current_]); + Local::New(isolate, data->realms_[data->realm_current_]); realm->Enter(); Handle result = script->Run(); realm->Exit(); @@ -272,7 +277,7 @@ bool Shell::ExecuteString(Isolate* isolate, #if !defined(V8_SHARED) } else { v8::TryCatch try_catch; - Context::Scope context_scope(utility_context_); + Context::Scope context_scope(isolate, utility_context_); Handle global = utility_context_->Global(); Handle fun = global->Get(String::New("Stringify")); Handle argv[1] = { result }; @@ -421,7 +426,7 @@ Handle Shell::RealmEval(const Arguments& args) { } Handle