diff options
author | Michaƫl Zasso <mic.besace@gmail.com> | 2015-10-06 08:42:38 +0200 |
---|---|---|
committer | Ali Ijaz Sheikh <ofrobots@google.com> | 2015-10-14 11:20:34 -0700 |
commit | d8011d1683fe0d977de2bea1147f5213d4490c5a (patch) | |
tree | 54967df8dc1732e59eef39e5c5b39fe99ad88977 /deps/v8/src/runtime | |
parent | d1a2e5357ef0357cec9b516fa9ac78cc38a984aa (diff) | |
download | node-new-d8011d1683fe0d977de2bea1147f5213d4490c5a.tar.gz |
deps: upgrade V8 to 4.6.85.23
PR-URL: https://github.com/nodejs/node/pull/3351
Reviewed-By: indutny - Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/runtime')
31 files changed, 1986 insertions, 2424 deletions
diff --git a/deps/v8/src/runtime/runtime-array.cc b/deps/v8/src/runtime/runtime-array.cc index d00df71576..fa0d91bf23 100644 --- a/deps/v8/src/runtime/runtime-array.cc +++ b/deps/v8/src/runtime/runtime-array.cc @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" +#include "src/conversions-inl.h" #include "src/elements.h" +#include "src/factory.h" #include "src/messages.h" -#include "src/runtime/runtime-utils.h" +#include "src/prototype.h" namespace v8 { namespace internal { @@ -133,7 +135,7 @@ class ArrayConcatVisitor { ~ArrayConcatVisitor() { clear_storage(); } void visit(uint32_t i, Handle<Object> elm) { - if (i > JSObject::kMaxElementCount - index_offset_) { + if (i >= JSObject::kMaxElementCount - index_offset_) { set_exceeds_array_limit(true); return; } @@ -154,8 +156,10 @@ class ArrayConcatVisitor { DCHECK(!fast_elements()); Handle<SeededNumberDictionary> dict( SeededNumberDictionary::cast(*storage_)); + // The object holding this backing store has just been allocated, so + // it cannot yet be used as a prototype. Handle<SeededNumberDictionary> result = - SeededNumberDictionary::AtNumberPut(dict, index, elm); + SeededNumberDictionary::AtNumberPut(dict, index, elm, false); if (!result.is_identical_to(dict)) { // Dictionary needed to grow. clear_storage(); @@ -207,8 +211,11 @@ class ArrayConcatVisitor { HandleScope loop_scope(isolate_); Handle<Object> element(current_storage->get(i), isolate_); if (!element->IsTheHole()) { + // The object holding this backing store has just been allocated, so + // it cannot yet be used as a prototype. Handle<SeededNumberDictionary> new_storage = - SeededNumberDictionary::AtNumberPut(slow_storage, i, element); + SeededNumberDictionary::AtNumberPut(slow_storage, i, element, + false); if (!new_storage.is_identical_to(slow_storage)) { slow_storage = loop_scope.CloseAndEscape(new_storage); } @@ -298,7 +305,6 @@ static uint32_t EstimateElementCount(Handle<JSArray> array) { case FAST_SLOPPY_ARGUMENTS_ELEMENTS: case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ - case EXTERNAL_##TYPE##_ELEMENTS: \ case TYPE##_ELEMENTS: TYPED_ARRAYS(TYPED_ARRAY_CASE) @@ -418,7 +424,6 @@ static void CollectElementIndices(Handle<JSObject> object, uint32_t range, } #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ case TYPE##_ELEMENTS: \ - case EXTERNAL_##TYPE##_ELEMENTS: TYPED_ARRAYS(TYPED_ARRAY_CASE) #undef TYPED_ARRAY_CASE @@ -439,12 +444,8 @@ static void CollectElementIndices(Handle<JSObject> object, uint32_t range, } case FAST_SLOPPY_ARGUMENTS_ELEMENTS: case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { - MaybeHandle<Object> length_obj = - Object::GetProperty(object, isolate->factory()->length_string()); - double length_num = length_obj.ToHandleChecked()->Number(); - uint32_t length = static_cast<uint32_t>(DoubleToInt32(length_num)); ElementsAccessor* accessor = object->GetElementsAccessor(); - for (uint32_t i = 0; i < length; i++) { + for (uint32_t i = 0; i < range; i++) { if (accessor->HasElement(object, i)) { indices->Add(i); } @@ -472,9 +473,9 @@ static bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver, if (!maybe.IsJust()) return false; if (maybe.FromJust()) { Handle<Object> element_value; - ASSIGN_RETURN_ON_EXCEPTION_VALUE( - isolate, element_value, - Runtime::GetElementOrCharAt(isolate, receiver, i), false); + ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, + Object::GetElement(isolate, receiver, i), + false); visitor->visit(i, element_value); } } @@ -610,15 +611,6 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, } break; } - case EXTERNAL_UINT8_CLAMPED_ELEMENTS: { - Handle<ExternalUint8ClampedArray> pixels( - ExternalUint8ClampedArray::cast(receiver->elements())); - for (uint32_t j = 0; j < length; j++) { - Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); - visitor->visit(j, e); - } - break; - } case UINT8_CLAMPED_ELEMENTS: { Handle<FixedUint8ClampedArray> pixels( FixedUint8ClampedArray::cast(receiver->elements())); @@ -628,81 +620,41 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, } break; } - case EXTERNAL_INT8_ELEMENTS: { - IterateTypedArrayElements<ExternalInt8Array, int8_t>( - isolate, receiver, true, true, visitor); - break; - } case INT8_ELEMENTS: { IterateTypedArrayElements<FixedInt8Array, int8_t>( isolate, receiver, true, true, visitor); break; } - case EXTERNAL_UINT8_ELEMENTS: { - IterateTypedArrayElements<ExternalUint8Array, uint8_t>( - isolate, receiver, true, true, visitor); - break; - } case UINT8_ELEMENTS: { IterateTypedArrayElements<FixedUint8Array, uint8_t>( isolate, receiver, true, true, visitor); break; } - case EXTERNAL_INT16_ELEMENTS: { - IterateTypedArrayElements<ExternalInt16Array, int16_t>( - isolate, receiver, true, true, visitor); - break; - } case INT16_ELEMENTS: { IterateTypedArrayElements<FixedInt16Array, int16_t>( isolate, receiver, true, true, visitor); break; } - case EXTERNAL_UINT16_ELEMENTS: { - IterateTypedArrayElements<ExternalUint16Array, uint16_t>( - isolate, receiver, true, true, visitor); - break; - } case UINT16_ELEMENTS: { IterateTypedArrayElements<FixedUint16Array, uint16_t>( isolate, receiver, true, true, visitor); break; } - case EXTERNAL_INT32_ELEMENTS: { - IterateTypedArrayElements<ExternalInt32Array, int32_t>( - isolate, receiver, true, false, visitor); - break; - } case INT32_ELEMENTS: { IterateTypedArrayElements<FixedInt32Array, int32_t>( isolate, receiver, true, false, visitor); break; } - case EXTERNAL_UINT32_ELEMENTS: { - IterateTypedArrayElements<ExternalUint32Array, uint32_t>( - isolate, receiver, true, false, visitor); - break; - } case UINT32_ELEMENTS: { IterateTypedArrayElements<FixedUint32Array, uint32_t>( isolate, receiver, true, false, visitor); break; } - case EXTERNAL_FLOAT32_ELEMENTS: { - IterateTypedArrayElements<ExternalFloat32Array, float>( - isolate, receiver, false, false, visitor); - break; - } case FLOAT32_ELEMENTS: { IterateTypedArrayElements<FixedFloat32Array, float>( isolate, receiver, false, false, visitor); break; } - case EXTERNAL_FLOAT64_ELEMENTS: { - IterateTypedArrayElements<ExternalFloat64Array, double>( - isolate, receiver, false, false, visitor); - break; - } case FLOAT64_ELEMENTS: { IterateTypedArrayElements<FixedFloat64Array, double>( isolate, receiver, false, false, visitor); @@ -1113,8 +1065,8 @@ static Object* ArrayConstructorCommon(Isolate* isolate, allocation_site = site; } - array = Handle<JSArray>::cast(factory->NewJSObjectFromMap( - initial_map, NOT_TENURED, true, allocation_site)); + array = Handle<JSArray>::cast( + factory->NewJSObjectFromMap(initial_map, NOT_TENURED, allocation_site)); } else { array = Handle<JSArray>::cast(factory->NewJSObject(constructor)); @@ -1233,8 +1185,7 @@ RUNTIME_FUNCTION(Runtime_NormalizeElements) { HandleScope scope(isolate); DCHECK(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); - RUNTIME_ASSERT(!array->HasExternalArrayElements() && - !array->HasFixedTypedArrayElements() && + RUNTIME_ASSERT(!array->HasFixedTypedArrayElements() && !array->IsJSGlobalProxy()); JSObject::NormalizeElements(array); return *array; diff --git a/deps/v8/src/runtime/runtime-atomics.cc b/deps/v8/src/runtime/runtime-atomics.cc index c9b78769cd..9b9fa0b12d 100644 --- a/deps/v8/src/runtime/runtime-atomics.cc +++ b/deps/v8/src/runtime/runtime-atomics.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/base/macros.h" #include "src/base/platform/mutex.h" -#include "src/conversions.h" -#include "src/runtime/runtime-utils.h" +#include "src/conversions-inl.h" +#include "src/factory.h" // Implement Atomic accesses to SharedArrayBuffers as defined in the // SharedArrayBuffer draft spec, found here @@ -103,69 +103,79 @@ inline void StoreSeqCst(uint64_t* p, uint64_t value) { #elif V8_CC_MSVC -#define _InterlockedCompareExchange32 _InterlockedCompareExchange -#define _InterlockedExchange32 _InterlockedExchange -#define _InterlockedExchangeAdd32 _InterlockedExchangeAdd -#define _InterlockedAnd32 _InterlockedAnd -#define _InterlockedOr32 _InterlockedOr -#define _InterlockedXor32 _InterlockedXor - -#define INTEGER_TYPES(V) \ - V(int8_t, 8, char) \ - V(uint8_t, 8, char) \ - V(int16_t, 16, short) /* NOLINT(runtime/int) */ \ - V(uint16_t, 16, short) /* NOLINT(runtime/int) */ \ - V(int32_t, 32, long) /* NOLINT(runtime/int) */ \ - V(uint32_t, 32, long) /* NOLINT(runtime/int) */ \ - V(int64_t, 64, LONGLONG) \ - V(uint64_t, 64, LONGLONG) - -#define ATOMIC_OPS(type, suffix, vctype) \ - inline type CompareExchangeSeqCst(volatile type* p, type oldval, \ - type newval) { \ - return _InterlockedCompareExchange##suffix( \ - reinterpret_cast<volatile vctype*>(p), bit_cast<vctype>(newval), \ - bit_cast<vctype>(oldval)); \ - } \ - inline type LoadSeqCst(volatile type* p) { return *p; } \ - inline void StoreSeqCst(volatile type* p, type value) { \ - _InterlockedExchange##suffix(reinterpret_cast<volatile vctype*>(p), \ - bit_cast<vctype>(value)); \ - } \ - inline type AddSeqCst(volatile type* p, type value) { \ - return _InterlockedExchangeAdd##suffix( \ - reinterpret_cast<volatile vctype*>(p), bit_cast<vctype>(value)); \ - } \ - inline type SubSeqCst(volatile type* p, type value) { \ - return _InterlockedExchangeAdd##suffix( \ - reinterpret_cast<volatile vctype*>(p), -bit_cast<vctype>(value)); \ - } \ - inline type AndSeqCst(volatile type* p, type value) { \ - return _InterlockedAnd##suffix(reinterpret_cast<volatile vctype*>(p), \ - bit_cast<vctype>(value)); \ - } \ - inline type OrSeqCst(volatile type* p, type value) { \ - return _InterlockedOr##suffix(reinterpret_cast<volatile vctype*>(p), \ - bit_cast<vctype>(value)); \ - } \ - inline type XorSeqCst(volatile type* p, type value) { \ - return _InterlockedXor##suffix(reinterpret_cast<volatile vctype*>(p), \ - bit_cast<vctype>(value)); \ - } \ - inline type ExchangeSeqCst(volatile type* p, type value) { \ - return _InterlockedExchange##suffix(reinterpret_cast<volatile vctype*>(p), \ - bit_cast<vctype>(value)); \ +#define InterlockedCompareExchange32 _InterlockedCompareExchange +#define InterlockedExchange32 _InterlockedExchange +#define InterlockedExchangeAdd32 _InterlockedExchangeAdd +#define InterlockedAnd32 _InterlockedAnd +#define InterlockedOr32 _InterlockedOr +#define InterlockedXor32 _InterlockedXor +#define InterlockedExchangeAdd16 _InterlockedExchangeAdd16 +#define InterlockedCompareExchange8 _InterlockedCompareExchange8 +#define InterlockedExchangeAdd8 _InterlockedExchangeAdd8 + +#define ATOMIC_OPS_INTEGER(type, suffix, vctype) \ + inline type AddSeqCst(type* p, type value) { \ + return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ + bit_cast<vctype>(value)); \ + } \ + inline type SubSeqCst(type* p, type value) { \ + return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ + -bit_cast<vctype>(value)); \ + } \ + inline type AndSeqCst(type* p, type value) { \ + return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p), \ + bit_cast<vctype>(value)); \ + } \ + inline type OrSeqCst(type* p, type value) { \ + return InterlockedOr##suffix(reinterpret_cast<vctype*>(p), \ + bit_cast<vctype>(value)); \ + } \ + inline type XorSeqCst(type* p, type value) { \ + return InterlockedXor##suffix(reinterpret_cast<vctype*>(p), \ + bit_cast<vctype>(value)); \ + } \ + inline type ExchangeSeqCst(type* p, type value) { \ + return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \ + bit_cast<vctype>(value)); \ + } + +#define ATOMIC_OPS_FLOAT(type, suffix, vctype) \ + inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \ + return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \ + bit_cast<vctype>(newval), \ + bit_cast<vctype>(oldval)); \ + } \ + inline type LoadSeqCst(type* p) { return *p; } \ + inline void StoreSeqCst(type* p, type value) { \ + InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \ + bit_cast<vctype>(value)); \ } -INTEGER_TYPES(ATOMIC_OPS) + +#define ATOMIC_OPS(type, suffix, vctype) \ + ATOMIC_OPS_INTEGER(type, suffix, vctype) \ + ATOMIC_OPS_FLOAT(type, suffix, vctype) + +ATOMIC_OPS(int8_t, 8, char) +ATOMIC_OPS(uint8_t, 8, char) +ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */ +ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ +ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */ +ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */ +ATOMIC_OPS_FLOAT(uint64_t, 64, LONGLONG) + +#undef ATOMIC_OPS_INTEGER +#undef ATOMIC_OPS_FLOAT #undef ATOMIC_OPS -#undef INTEGER_TYPES -#undef _InterlockedCompareExchange32 -#undef _InterlockedExchange32 -#undef _InterlockedExchangeAdd32 -#undef _InterlockedAnd32 -#undef _InterlockedOr32 -#undef _InterlockedXor32 +#undef InterlockedCompareExchange32 +#undef InterlockedExchange32 +#undef InterlockedExchangeAdd32 +#undef InterlockedAnd32 +#undef InterlockedOr32 +#undef InterlockedXor32 +#undef InterlockedExchangeAdd16 +#undef InterlockedCompareExchange8 +#undef InterlockedExchangeAdd8 #else diff --git a/deps/v8/src/runtime/runtime-classes.cc b/deps/v8/src/runtime/runtime-classes.cc index 97a19c1bc7..8692b9b800 100644 --- a/deps/v8/src/runtime/runtime-classes.cc +++ b/deps/v8/src/runtime/runtime-classes.cc @@ -2,17 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "src/runtime/runtime-utils.h" + #include <stdlib.h> #include <limits> -#include "src/v8.h" - #include "src/arguments.h" -#include "src/debug.h" +#include "src/debug/debug.h" +#include "src/frames-inl.h" #include "src/messages.h" #include "src/runtime/runtime.h" -#include "src/runtime/runtime-utils.h" - namespace v8 { namespace internal { @@ -93,16 +92,10 @@ RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) { } -RUNTIME_FUNCTION(Runtime_DefineClass) { - HandleScope scope(isolate); - DCHECK(args.length() == 6); - CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2); - CONVERT_ARG_HANDLE_CHECKED(Script, script, 3); - CONVERT_SMI_ARG_CHECKED(start_position, 4); - CONVERT_SMI_ARG_CHECKED(end_position, 5); - +static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name, + Handle<Object> super_class, + Handle<JSFunction> constructor, + int start_position, int end_position) { Handle<Object> prototype_parent; Handle<Object> constructor_parent; @@ -113,31 +106,38 @@ RUNTIME_FUNCTION(Runtime_DefineClass) { prototype_parent = isolate->factory()->null_value(); } else if (super_class->IsSpecFunction()) { if (Handle<JSFunction>::cast(super_class)->shared()->is_generator()) { - THROW_NEW_ERROR_RETURN_FAILURE( + THROW_NEW_ERROR( isolate, - NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class)); + NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class), + Object); } - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + ASSIGN_RETURN_ON_EXCEPTION( isolate, prototype_parent, Runtime::GetObjectProperty(isolate, super_class, isolate->factory()->prototype_string(), - SLOPPY)); + SLOPPY), + Object); if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) { - THROW_NEW_ERROR_RETURN_FAILURE( + THROW_NEW_ERROR( isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject, - prototype_parent)); + prototype_parent), + Object); } constructor_parent = super_class; } else { // TODO(arv): Should be IsConstructor. - THROW_NEW_ERROR_RETURN_FAILURE( + THROW_NEW_ERROR( isolate, - NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class)); + NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class), + Object); } } Handle<Map> map = isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + if (constructor->map()->is_strong()) { + map->set_is_strong(); + } Map::SetPrototype(map, prototype_parent); map->SetConstructor(*constructor); Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map); @@ -155,42 +155,81 @@ RUNTIME_FUNCTION(Runtime_DefineClass) { JSFunction::SetPrototype(constructor, prototype); PropertyAttributes attribs = static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); - RETURN_FAILURE_ON_EXCEPTION( - isolate, JSObject::SetOwnPropertyIgnoreAttributes( - constructor, isolate->factory()->prototype_string(), - prototype, attribs)); + RETURN_ON_EXCEPTION(isolate, + JSObject::SetOwnPropertyIgnoreAttributes( + constructor, isolate->factory()->prototype_string(), + prototype, attribs), + Object); // TODO(arv): Only do this conditionally. Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol()); - RETURN_FAILURE_ON_EXCEPTION( + RETURN_ON_EXCEPTION( isolate, JSObject::SetOwnPropertyIgnoreAttributes( - constructor, home_object_symbol, prototype, DONT_ENUM)); + constructor, home_object_symbol, prototype, DONT_ENUM), + Object); if (!constructor_parent.is_null()) { - RETURN_FAILURE_ON_EXCEPTION( - isolate, - JSObject::SetPrototype(constructor, constructor_parent, false)); + RETURN_ON_EXCEPTION( + isolate, JSObject::SetPrototype(constructor, constructor_parent, false), + Object); } JSObject::AddProperty(prototype, isolate->factory()->constructor_string(), constructor, DONT_ENUM); // Install private properties that are used to construct the FunctionToString. - RETURN_FAILURE_ON_EXCEPTION( - isolate, Object::SetProperty(constructor, - isolate->factory()->class_script_symbol(), - script, STRICT)); - RETURN_FAILURE_ON_EXCEPTION( + RETURN_ON_EXCEPTION( isolate, Object::SetProperty( constructor, isolate->factory()->class_start_position_symbol(), - handle(Smi::FromInt(start_position), isolate), STRICT)); - RETURN_FAILURE_ON_EXCEPTION( + handle(Smi::FromInt(start_position), isolate), STRICT), + Object); + RETURN_ON_EXCEPTION( isolate, Object::SetProperty( constructor, isolate->factory()->class_end_position_symbol(), - handle(Smi::FromInt(end_position), isolate), STRICT)); + handle(Smi::FromInt(end_position), isolate), STRICT), + Object); - return *constructor; + return constructor; +} + + +RUNTIME_FUNCTION(Runtime_DefineClass) { + HandleScope scope(isolate); + DCHECK(args.length() == 5); + CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2); + CONVERT_SMI_ARG_CHECKED(start_position, 3); + CONVERT_SMI_ARG_CHECKED(end_position, 4); + + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, DefineClass(isolate, name, super_class, constructor, + start_position, end_position)); + return *result; +} + + +RUNTIME_FUNCTION(Runtime_DefineClassStrong) { + HandleScope scope(isolate); + DCHECK(args.length() == 5); + CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2); + CONVERT_SMI_ARG_CHECKED(start_position, 3); + CONVERT_SMI_ARG_CHECKED(end_position, 4); + + if (super_class->IsNull()) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kStrongExtendNull)); + } + + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, DefineClass(isolate, name, super_class, constructor, + start_position, end_position)); + return *result; } @@ -208,37 +247,46 @@ RUNTIME_FUNCTION(Runtime_DefineClassMethod) { } +RUNTIME_FUNCTION(Runtime_FinalizeClassDefinition) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(JSObject, constructor, 0); + CONVERT_ARG_HANDLE_CHECKED(JSObject, prototype, 1); + + JSObject::MigrateSlowToFast(prototype, 0, "RuntimeToFastProperties"); + JSObject::MigrateSlowToFast(constructor, 0, "RuntimeToFastProperties"); + + if (constructor->map()->is_strong()) { + DCHECK(prototype->map()->is_strong()); + RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::Freeze(prototype)); + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + JSObject::Freeze(constructor)); + return *result; + } + return *constructor; +} + + RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) { HandleScope shs(isolate); DCHECK(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); - Handle<Object> script; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, script, - Object::GetProperty(fun, isolate->factory()->class_script_symbol())); - if (!script->IsScript()) { - return isolate->heap()->undefined_value(); - } - Handle<Symbol> start_position_symbol( isolate->heap()->class_start_position_symbol()); - Handle<Object> start_position; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, start_position, Object::GetProperty(fun, start_position_symbol)); + Handle<Object> start_position = + JSReceiver::GetDataProperty(fun, start_position_symbol); + if (!start_position->IsSmi()) return isolate->heap()->undefined_value(); Handle<Symbol> end_position_symbol( isolate->heap()->class_end_position_symbol()); - Handle<Object> end_position; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, end_position, Object::GetProperty(fun, end_position_symbol)); - - if (!start_position->IsSmi() || !end_position->IsSmi() || - !Handle<Script>::cast(script)->HasValidSource()) { - return isolate->ThrowIllegalOperation(); - } + Handle<Object> end_position = + JSReceiver::GetDataProperty(fun, end_position_symbol); + CHECK(end_position->IsSmi()); - Handle<String> source(String::cast(Handle<Script>::cast(script)->source())); + Handle<String> source( + String::cast(Script::cast(fun->shared()->script())->source())); return *isolate->factory()->NewSubString( source, Handle<Smi>::cast(start_position)->value(), Handle<Smi>::cast(end_position)->value()); @@ -476,14 +524,49 @@ RUNTIME_FUNCTION(Runtime_HandleStepInForDerivedConstructors) { RUNTIME_FUNCTION(Runtime_DefaultConstructorCallSuper) { - UNIMPLEMENTED(); - return nullptr; -} + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, original_constructor, 0); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, actual_constructor, 1); + JavaScriptFrameIterator it(isolate); + // Prepare the callee to the super call. The super constructor is stored as + // the prototype of the constructor we are currently executing. + Handle<Object> super_constructor; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, super_constructor, + Runtime::GetPrototype(isolate, actual_constructor)); + + // Find the frame that holds the actual arguments passed to the function. + it.AdvanceToArgumentsFrame(); + JavaScriptFrame* frame = it.frame(); + + // Prepare the array containing all passed arguments. + int argument_count = frame->GetArgumentsLength(); + Handle<FixedArray> elements = + isolate->factory()->NewUninitializedFixedArray(argument_count); + for (int i = 0; i < argument_count; ++i) { + elements->set(i, frame->GetParameter(i)); + } + Handle<JSArray> arguments = isolate->factory()->NewJSArrayWithElements( + elements, FAST_ELEMENTS, argument_count); + + // Call $reflectConstruct(<super>, <args>, <new.target>) now. + Handle<Object> reflect; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, reflect, + Object::GetProperty(isolate, + handle(isolate->native_context()->builtins()), + "$reflectConstruct")); + RUNTIME_ASSERT(reflect->IsJSFunction()); // Depends on --harmony-reflect. + Handle<Object> argv[] = {super_constructor, arguments, original_constructor}; + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, + Execution::Call(isolate, reflect, isolate->factory()->undefined_value(), + arraysize(argv), argv)); -RUNTIME_FUNCTION(Runtime_CallSuperWithSpread) { - UNIMPLEMENTED(); - return nullptr; + return *result; } } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-collections.cc b/deps/v8/src/runtime/runtime-collections.cc index 1ba1e34356..3450fca0e2 100644 --- a/deps/v8/src/runtime/runtime-collections.cc +++ b/deps/v8/src/runtime/runtime-collections.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" - -#include "src/arguments.h" #include "src/runtime/runtime-utils.h" +#include "src/arguments.h" +#include "src/conversions-inl.h" +#include "src/factory.h" namespace v8 { namespace internal { @@ -299,7 +299,7 @@ RUNTIME_FUNCTION(Runtime_MapIteratorNext) { void Runtime::WeakCollectionInitialize( Isolate* isolate, Handle<JSWeakCollection> weak_collection) { - DCHECK(weak_collection->map()->inobject_properties() == 0); + DCHECK_EQ(0, weak_collection->map()->GetInObjectProperties()); Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0); weak_collection->set_table(*table); } diff --git a/deps/v8/src/runtime/runtime-compiler.cc b/deps/v8/src/runtime/runtime-compiler.cc index 4cfa84ac44..e7f567f885 100644 --- a/deps/v8/src/runtime/runtime-compiler.cc +++ b/deps/v8/src/runtime/runtime-compiler.cc @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/compiler.h" #include "src/deoptimizer.h" -#include "src/frames.h" -#include "src/full-codegen.h" +#include "src/frames-inl.h" +#include "src/full-codegen/full-codegen.h" #include "src/messages.h" -#include "src/runtime/runtime-utils.h" #include "src/v8threads.h" #include "src/vm-state-inl.h" @@ -35,8 +34,8 @@ RUNTIME_FUNCTION(Runtime_CompileLazy) { Handle<Code> code; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code, Compiler::GetLazyCode(function)); - DCHECK(code->kind() == Code::FUNCTION || - code->kind() == Code::OPTIMIZED_FUNCTION); + DCHECK(code->IsJavaScriptCode()); + function->ReplaceCode(*code); return *code; } @@ -132,9 +131,7 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) { RUNTIME_ASSERT(frame->function()->IsJSFunction()); DCHECK(frame->function() == *function); - // Avoid doing too much work when running with --always-opt and keep - // the optimized code around. - if (FLAG_always_opt || type == Deoptimizer::LAZY) { + if (type == Deoptimizer::LAZY) { return isolate->heap()->undefined_value(); } diff --git a/deps/v8/src/runtime/runtime-date.cc b/deps/v8/src/runtime/runtime-date.cc index c47b158564..4231d82c34 100644 --- a/deps/v8/src/runtime/runtime-date.cc +++ b/deps/v8/src/runtime/runtime-date.cc @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" +#include "src/conversions-inl.h" #include "src/date.h" #include "src/dateparser-inl.h" +#include "src/factory.h" #include "src/messages.h" -#include "src/runtime/runtime-utils.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime-debug.cc b/deps/v8/src/runtime/runtime-debug.cc index e7aaed1f6f..1cd524f17c 100644 --- a/deps/v8/src/runtime/runtime-debug.cc +++ b/deps/v8/src/runtime/runtime-debug.cc @@ -2,16 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" -#include "src/accessors.h" #include "src/arguments.h" -#include "src/compiler.h" -#include "src/debug.h" -#include "src/deoptimizer.h" -#include "src/parser.h" +#include "src/debug/debug.h" +#include "src/debug/debug-evaluate.h" +#include "src/debug/debug-frames.h" +#include "src/debug/debug-scopes.h" +#include "src/frames-inl.h" #include "src/runtime/runtime.h" -#include "src/runtime/runtime-utils.h" namespace v8 { namespace internal { @@ -19,20 +18,19 @@ namespace internal { RUNTIME_FUNCTION(Runtime_DebugBreak) { SealHandleScope shs(isolate); DCHECK(args.length() == 0); - isolate->debug()->HandleDebugBreak(); + // Get the top-most JavaScript frame. + JavaScriptFrameIterator it(isolate); + isolate->debug()->Break(args, it.frame()); + isolate->debug()->SetAfterBreakTarget(it.frame()); return isolate->heap()->undefined_value(); } -// Helper functions for wrapping and unwrapping stack frame ids. -static Smi* WrapFrameId(StackFrame::Id id) { - DCHECK(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4))); - return Smi::FromInt(id >> 2); -} - - -static StackFrame::Id UnwrapFrameId(int wrapped) { - return static_cast<StackFrame::Id>(wrapped << 2); +RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) { + SealHandleScope shs(isolate); + DCHECK(args.length() == 0); + isolate->debug()->HandleDebugBreak(); + return isolate->heap()->undefined_value(); } @@ -311,9 +309,8 @@ RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) { if (name->AsArrayIndex(&index)) { Handle<FixedArray> details = isolate->factory()->NewFixedArray(2); Handle<Object> element_or_char; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, element_or_char, - Runtime::GetElementOrCharAt(isolate, obj, index)); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_or_char, + Object::GetElement(isolate, obj, index)); details->set(0, *element_or_char); details->set(1, PropertyDetails::Empty().AsSmi()); return *isolate->factory()->NewJSArrayWithElements(details); @@ -465,93 +462,6 @@ RUNTIME_FUNCTION(Runtime_GetFrameCount) { } -class FrameInspector { - public: - FrameInspector(JavaScriptFrame* frame, int inlined_jsframe_index, - Isolate* isolate) - : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) { - has_adapted_arguments_ = frame_->has_adapted_arguments(); - is_bottommost_ = inlined_jsframe_index == 0; - is_optimized_ = frame_->is_optimized(); - // Calculate the deoptimized frame. - if (frame->is_optimized()) { - // TODO(turbofan): Revisit once we support deoptimization. - if (frame->LookupCode()->is_turbofanned() && - frame->function()->shared()->asm_function() && - !FLAG_turbo_asm_deoptimization) { - is_optimized_ = false; - return; - } - - deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame( - frame, inlined_jsframe_index, isolate); - } - } - - ~FrameInspector() { - // Get rid of the calculated deoptimized frame if any. - if (deoptimized_frame_ != NULL) { - Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_); - } - } - - int GetParametersCount() { - return is_optimized_ ? deoptimized_frame_->parameters_count() - : frame_->ComputeParametersCount(); - } - int expression_count() { return deoptimized_frame_->expression_count(); } - Object* GetFunction() { - return is_optimized_ ? deoptimized_frame_->GetFunction() - : frame_->function(); - } - Object* GetParameter(int index) { - return is_optimized_ ? deoptimized_frame_->GetParameter(index) - : frame_->GetParameter(index); - } - Object* GetExpression(int index) { - // TODO(turbofan): Revisit once we support deoptimization. - if (frame_->LookupCode()->is_turbofanned() && - frame_->function()->shared()->asm_function() && - !FLAG_turbo_asm_deoptimization) { - return isolate_->heap()->undefined_value(); - } - return is_optimized_ ? deoptimized_frame_->GetExpression(index) - : frame_->GetExpression(index); - } - int GetSourcePosition() { - return is_optimized_ ? deoptimized_frame_->GetSourcePosition() - : frame_->LookupCode()->SourcePosition(frame_->pc()); - } - bool IsConstructor() { - return is_optimized_ && !is_bottommost_ - ? deoptimized_frame_->HasConstructStub() - : frame_->IsConstructor(); - } - Object* GetContext() { - return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context(); - } - - // To inspect all the provided arguments the frame might need to be - // replaced with the arguments frame. - void SetArgumentsFrame(JavaScriptFrame* frame) { - DCHECK(has_adapted_arguments_); - frame_ = frame; - is_optimized_ = frame_->is_optimized(); - DCHECK(!is_optimized_); - } - - private: - JavaScriptFrame* frame_; - DeoptimizedFrameInfo* deoptimized_frame_; - Isolate* isolate_; - bool is_optimized_; - bool is_bottommost_; - bool has_adapted_arguments_; - - DISALLOW_COPY_AND_ASSIGN(FrameInspector); -}; - - static const int kFrameDetailsFrameIdIndex = 0; static const int kFrameDetailsReceiverIndex = 1; static const int kFrameDetailsFunctionIndex = 2; @@ -564,34 +474,6 @@ static const int kFrameDetailsFlagsIndex = 8; static const int kFrameDetailsFirstDynamicIndex = 9; -static SaveContext* FindSavedContextForFrame(Isolate* isolate, - JavaScriptFrame* frame) { - SaveContext* save = isolate->save_context(); - while (save != NULL && !save->IsBelowFrame(frame)) { - save = save->prev(); - } - DCHECK(save != NULL); - return save; -} - - -// Advances the iterator to the frame that matches the index and returns the -// inlined frame index, or -1 if not found. Skips native JS functions. -int Runtime::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index) { - int count = -1; - for (; !it->done(); it->Advance()) { - List<FrameSummary> frames(FLAG_max_inlining_levels + 1); - it->frame()->Summarize(&frames); - for (int i = frames.length() - 1; i >= 0; i--) { - // Omit functions from native and extension scripts. - if (!frames[i].function()->IsSubjectToDebugging()) continue; - if (++count == index) return i; - } - } - return -1; -} - - // Return an array with frame details // args[0]: number: break id // args[1]: number: frame index @@ -627,7 +509,8 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { JavaScriptFrameIterator it(isolate, id); // Inlined frame index in optimized frame, starting from outer function. - int inlined_jsframe_index = Runtime::FindIndexedNonNativeFrame(&it, index); + int inlined_jsframe_index = + DebugFrameHelper::FindIndexedNonNativeFrame(&it, index); if (inlined_jsframe_index == -1) return heap->undefined_value(); FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate); @@ -635,10 +518,12 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { // Traverse the saved contexts chain to find the active context for the // selected frame. - SaveContext* save = FindSavedContextForFrame(isolate, it.frame()); + SaveContext* save = + DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame()); // Get the frame id. - Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); + Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()), + isolate); // Find source position in unoptimized code. int position = frame_inspector.GetSourcePosition(); @@ -855,932 +740,6 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { } -static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info, - Handle<String> parameter_name) { - VariableMode mode; - VariableLocation location; - InitializationFlag init_flag; - MaybeAssignedFlag maybe_assigned_flag; - return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &location, - &init_flag, &maybe_assigned_flag) != -1; -} - - -static Handle<Context> MaterializeReceiver(Isolate* isolate, - Handle<Context> target, - Handle<JSFunction> function, - JavaScriptFrame* frame) { - Handle<SharedFunctionInfo> shared(function->shared()); - Handle<ScopeInfo> scope_info(shared->scope_info()); - Handle<Object> receiver; - switch (scope_info->scope_type()) { - case FUNCTION_SCOPE: { - VariableMode mode; - VariableLocation location; - InitializationFlag init_flag; - MaybeAssignedFlag maybe_assigned_flag; - - // Don't bother creating a fake context node if "this" is in the context - // already. - if (ScopeInfo::ContextSlotIndex( - scope_info, isolate->factory()->this_string(), &mode, &location, - &init_flag, &maybe_assigned_flag) >= 0) { - return target; - } - receiver = handle(frame->receiver(), isolate); - break; - } - case MODULE_SCOPE: - receiver = isolate->factory()->undefined_value(); - break; - case SCRIPT_SCOPE: - receiver = handle(function->global_proxy(), isolate); - break; - default: - // For eval code, arrow functions, and the like, there's no "this" binding - // to materialize. - return target; - } - - return isolate->factory()->NewCatchContext( - function, target, isolate->factory()->this_string(), receiver); -} - - -// Create a plain JSObject which materializes the local scope for the specified -// frame. -static void MaterializeStackLocalsWithFrameInspector( - Isolate* isolate, Handle<JSObject> target, Handle<ScopeInfo> scope_info, - FrameInspector* frame_inspector) { - // First fill all parameters. - for (int i = 0; i < scope_info->ParameterCount(); ++i) { - // Do not materialize the parameter if it is shadowed by a context local. - Handle<String> name(scope_info->ParameterName(i)); - if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; - - DCHECK_NOT_NULL(frame_inspector); - - HandleScope scope(isolate); - Handle<Object> value(i < frame_inspector->GetParametersCount() - ? frame_inspector->GetParameter(i) - : isolate->heap()->undefined_value(), - isolate); - DCHECK(!value->IsTheHole()); - - JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); - } - - // Second fill all stack locals. - for (int i = 0; i < scope_info->StackLocalCount(); ++i) { - if (scope_info->LocalIsSynthetic(i)) continue; - Handle<String> name(scope_info->StackLocalName(i)); - Handle<Object> value( - frame_inspector->GetExpression(scope_info->StackLocalIndex(i)), - isolate); - if (value->IsTheHole()) { - value = isolate->factory()->undefined_value(); - } - - JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); - } -} - -static void MaterializeStackLocalsWithFrameInspector( - Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, - FrameInspector* frame_inspector) { - Handle<SharedFunctionInfo> shared(function->shared()); - Handle<ScopeInfo> scope_info(shared->scope_info()); - - MaterializeStackLocalsWithFrameInspector(isolate, target, scope_info, - frame_inspector); -} - - -static void UpdateStackLocalsFromMaterializedObject( - Isolate* isolate, Handle<JSObject> target, Handle<ScopeInfo> scope_info, - JavaScriptFrame* frame, int inlined_jsframe_index) { - if (inlined_jsframe_index != 0 || frame->is_optimized()) { - // Optimized frames are not supported. - // TODO(yangguo): make sure all code deoptimized when debugger is active - // and assert that this cannot happen. - return; - } - - // Parameters. - for (int i = 0; i < scope_info->ParameterCount(); ++i) { - // Shadowed parameters were not materialized. - Handle<String> name(scope_info->ParameterName(i)); - if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; - - DCHECK(!frame->GetParameter(i)->IsTheHole()); - HandleScope scope(isolate); - Handle<Object> value = - Object::GetPropertyOrElement(target, name).ToHandleChecked(); - frame->SetParameterValue(i, *value); - } - - // Stack locals. - for (int i = 0; i < scope_info->StackLocalCount(); ++i) { - if (scope_info->LocalIsSynthetic(i)) continue; - int index = scope_info->StackLocalIndex(i); - if (frame->GetExpression(index)->IsTheHole()) continue; - HandleScope scope(isolate); - Handle<Object> value = Object::GetPropertyOrElement( - target, handle(scope_info->StackLocalName(i), - isolate)).ToHandleChecked(); - frame->SetExpression(index, *value); - } -} - - -MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext( - Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, - JavaScriptFrame* frame) { - HandleScope scope(isolate); - Handle<SharedFunctionInfo> shared(function->shared()); - Handle<ScopeInfo> scope_info(shared->scope_info()); - - if (!scope_info->HasContext()) return target; - - // Third fill all context locals. - Handle<Context> frame_context(Context::cast(frame->context())); - Handle<Context> function_context(frame_context->declaration_context()); - ScopeInfo::CopyContextLocalsToScopeObject(scope_info, function_context, - target); - - // Finally copy any properties from the function context extension. - // These will be variables introduced by eval. - if (function_context->closure() == *function) { - if (function_context->has_extension() && - !function_context->IsNativeContext()) { - Handle<JSObject> ext(JSObject::cast(function_context->extension())); - Handle<FixedArray> keys; - ASSIGN_RETURN_ON_EXCEPTION( - isolate, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), - JSObject); - - for (int i = 0; i < keys->length(); i++) { - // Names of variables introduced by eval are strings. - DCHECK(keys->get(i)->IsString()); - Handle<String> key(String::cast(keys->get(i))); - Handle<Object> value; - ASSIGN_RETURN_ON_EXCEPTION( - isolate, value, Object::GetPropertyOrElement(ext, key), JSObject); - RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( - isolate, target, key, value, SLOPPY), - JSObject); - } - } - } - - return target; -} - - -MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScriptScope( - Handle<GlobalObject> global) { - Isolate* isolate = global->GetIsolate(); - Handle<ScriptContextTable> script_contexts( - global->native_context()->script_context_table()); - - Handle<JSObject> script_scope = - isolate->factory()->NewJSObject(isolate->object_function()); - - for (int context_index = 0; context_index < script_contexts->used(); - context_index++) { - Handle<Context> context = - ScriptContextTable::GetContext(script_contexts, context_index); - Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); - ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, - script_scope); - } - return script_scope; -} - - -MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope( - Isolate* isolate, JavaScriptFrame* frame, int inlined_jsframe_index) { - FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); - Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); - - Handle<JSObject> local_scope = - isolate->factory()->NewJSObject(isolate->object_function()); - MaterializeStackLocalsWithFrameInspector(isolate, local_scope, function, - &frame_inspector); - - return MaterializeLocalContext(isolate, local_scope, function, frame); -} - - -// Set the context local variable value. -static bool SetContextLocalValue(Isolate* isolate, Handle<ScopeInfo> scope_info, - Handle<Context> context, - Handle<String> variable_name, - Handle<Object> new_value) { - for (int i = 0; i < scope_info->ContextLocalCount(); i++) { - Handle<String> next_name(scope_info->ContextLocalName(i)); - if (String::Equals(variable_name, next_name)) { - VariableMode mode; - VariableLocation location; - InitializationFlag init_flag; - MaybeAssignedFlag maybe_assigned_flag; - int context_index = - ScopeInfo::ContextSlotIndex(scope_info, next_name, &mode, &location, - &init_flag, &maybe_assigned_flag); - context->set(context_index, *new_value); - return true; - } - } - - return false; -} - - -static bool SetLocalVariableValue(Isolate* isolate, JavaScriptFrame* frame, - int inlined_jsframe_index, - Handle<String> variable_name, - Handle<Object> new_value) { - if (inlined_jsframe_index != 0 || frame->is_optimized()) { - // Optimized frames are not supported. - return false; - } - - Handle<JSFunction> function(frame->function()); - Handle<SharedFunctionInfo> shared(function->shared()); - Handle<ScopeInfo> scope_info(shared->scope_info()); - - bool default_result = false; - - // Parameters. - for (int i = 0; i < scope_info->ParameterCount(); ++i) { - HandleScope scope(isolate); - if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) { - frame->SetParameterValue(i, *new_value); - // Argument might be shadowed in heap context, don't stop here. - default_result = true; - } - } - - // Stack locals. - for (int i = 0; i < scope_info->StackLocalCount(); ++i) { - HandleScope scope(isolate); - if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { - frame->SetExpression(scope_info->StackLocalIndex(i), *new_value); - return true; - } - } - - if (scope_info->HasContext()) { - // Context locals. - Handle<Context> frame_context(Context::cast(frame->context())); - Handle<Context> function_context(frame_context->declaration_context()); - if (SetContextLocalValue(isolate, scope_info, function_context, - variable_name, new_value)) { - return true; - } - - // Function context extension. These are variables introduced by eval. - if (function_context->closure() == *function) { - if (function_context->has_extension() && - !function_context->IsNativeContext()) { - Handle<JSObject> ext(JSObject::cast(function_context->extension())); - - Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name); - DCHECK(maybe.IsJust()); - if (maybe.FromJust()) { - // We don't expect this to do anything except replacing - // property value. - Runtime::SetObjectProperty(isolate, ext, variable_name, new_value, - SLOPPY).Assert(); - return true; - } - } - } - } - - return default_result; -} - - -static bool SetBlockVariableValue(Isolate* isolate, - Handle<Context> block_context, - Handle<ScopeInfo> scope_info, - JavaScriptFrame* frame, - Handle<String> variable_name, - Handle<Object> new_value) { - if (frame != nullptr) { - for (int i = 0; i < scope_info->StackLocalCount(); ++i) { - HandleScope scope(isolate); - if (String::Equals(handle(scope_info->StackLocalName(i)), - variable_name)) { - frame->SetExpression(scope_info->StackLocalIndex(i), *new_value); - return true; - } - } - } - if (!block_context.is_null()) { - return SetContextLocalValue(block_context->GetIsolate(), scope_info, - block_context, variable_name, new_value); - } - return false; -} - - -// Create a plain JSObject which materializes the closure content for the -// context. -static Handle<JSObject> MaterializeClosure(Isolate* isolate, - Handle<Context> context) { - DCHECK(context->IsFunctionContext()); - - Handle<SharedFunctionInfo> shared(context->closure()->shared()); - Handle<ScopeInfo> scope_info(shared->scope_info()); - - // Allocate and initialize a JSObject with all the content of this function - // closure. - Handle<JSObject> closure_scope = - isolate->factory()->NewJSObject(isolate->object_function()); - - // Fill all context locals to the context extension. - ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, closure_scope); - - // Finally copy any properties from the function context extension. This will - // be variables introduced by eval. - if (context->has_extension()) { - Handle<JSObject> ext(JSObject::cast(context->extension())); - DCHECK(ext->IsJSContextExtensionObject()); - Handle<FixedArray> keys = - JSReceiver::GetKeys(ext, JSReceiver::OWN_ONLY).ToHandleChecked(); - - for (int i = 0; i < keys->length(); i++) { - HandleScope scope(isolate); - // Names of variables introduced by eval are strings. - DCHECK(keys->get(i)->IsString()); - Handle<String> key(String::cast(keys->get(i))); - Handle<Object> value = Object::GetProperty(ext, key).ToHandleChecked(); - JSObject::SetOwnPropertyIgnoreAttributes(closure_scope, key, value, NONE) - .Check(); - } - } - - return closure_scope; -} - - -// This method copies structure of MaterializeClosure method above. -static bool SetClosureVariableValue(Isolate* isolate, Handle<Context> context, - Handle<String> variable_name, - Handle<Object> new_value) { - DCHECK(context->IsFunctionContext()); - - Handle<SharedFunctionInfo> shared(context->closure()->shared()); - Handle<ScopeInfo> scope_info(shared->scope_info()); - - // Context locals to the context extension. - if (SetContextLocalValue(isolate, scope_info, context, variable_name, - new_value)) { - return true; - } - - // Properties from the function context extension. This will - // be variables introduced by eval. - if (context->has_extension()) { - Handle<JSObject> ext(JSObject::cast(context->extension())); - DCHECK(ext->IsJSContextExtensionObject()); - Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name); - DCHECK(maybe.IsJust()); - if (maybe.FromJust()) { - // We don't expect this to do anything except replacing property value. - JSObject::SetOwnPropertyIgnoreAttributes(ext, variable_name, new_value, - NONE).Check(); - return true; - } - } - - return false; -} - - -static bool SetScriptVariableValue(Handle<Context> context, - Handle<String> variable_name, - Handle<Object> new_value) { - Handle<ScriptContextTable> script_contexts( - context->global_object()->native_context()->script_context_table()); - ScriptContextTable::LookupResult lookup_result; - if (ScriptContextTable::Lookup(script_contexts, variable_name, - &lookup_result)) { - Handle<Context> script_context = ScriptContextTable::GetContext( - script_contexts, lookup_result.context_index); - script_context->set(lookup_result.slot_index, *new_value); - return true; - } - - return false; -} - - -// Create a plain JSObject which materializes the scope for the specified -// catch context. -static Handle<JSObject> MaterializeCatchScope(Isolate* isolate, - Handle<Context> context) { - DCHECK(context->IsCatchContext()); - Handle<String> name(String::cast(context->extension())); - Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX), - isolate); - Handle<JSObject> catch_scope = - isolate->factory()->NewJSObject(isolate->object_function()); - JSObject::SetOwnPropertyIgnoreAttributes(catch_scope, name, thrown_object, - NONE).Check(); - return catch_scope; -} - - -static bool SetCatchVariableValue(Isolate* isolate, Handle<Context> context, - Handle<String> variable_name, - Handle<Object> new_value) { - DCHECK(context->IsCatchContext()); - Handle<String> name(String::cast(context->extension())); - if (!String::Equals(name, variable_name)) { - return false; - } - context->set(Context::THROWN_OBJECT_INDEX, *new_value); - return true; -} - - -// Create a plain JSObject which materializes the block scope for the specified -// block context. -static Handle<JSObject> MaterializeBlockScope(Isolate* isolate, - Handle<ScopeInfo> scope_info, - Handle<Context> context, - JavaScriptFrame* frame, - int inlined_jsframe_index) { - Handle<JSObject> block_scope = - isolate->factory()->NewJSObject(isolate->object_function()); - - if (frame != nullptr) { - FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); - MaterializeStackLocalsWithFrameInspector(isolate, block_scope, scope_info, - &frame_inspector); - } - - if (!context.is_null()) { - Handle<ScopeInfo> scope_info_from_context( - ScopeInfo::cast(context->extension())); - // Fill all context locals. - ScopeInfo::CopyContextLocalsToScopeObject(scope_info_from_context, context, - block_scope); - } - - return block_scope; -} - - -// Create a plain JSObject which materializes the module scope for the specified -// module context. -MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope( - Isolate* isolate, Handle<Context> context) { - DCHECK(context->IsModuleContext()); - Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); - - // Allocate and initialize a JSObject with all the members of the debugged - // module. - Handle<JSObject> module_scope = - isolate->factory()->NewJSObject(isolate->object_function()); - - // Fill all context locals. - ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, module_scope); - - return module_scope; -} - - -// Iterate over the actual scopes visible from a stack frame or from a closure. -// The iteration proceeds from the innermost visible nested scope outwards. -// All scopes are backed by an actual context except the local scope, -// which is inserted "artificially" in the context chain. -class ScopeIterator { - public: - enum ScopeType { - ScopeTypeGlobal = 0, - ScopeTypeLocal, - ScopeTypeWith, - ScopeTypeClosure, - ScopeTypeCatch, - ScopeTypeBlock, - ScopeTypeScript, - ScopeTypeModule - }; - - ScopeIterator(Isolate* isolate, JavaScriptFrame* frame, - int inlined_jsframe_index, bool ignore_nested_scopes = false) - : isolate_(isolate), - frame_(frame), - inlined_jsframe_index_(inlined_jsframe_index), - function_(frame->function()), - context_(Context::cast(frame->context())), - nested_scope_chain_(4), - seen_script_scope_(false), - failed_(false) { - // Catch the case when the debugger stops in an internal function. - Handle<SharedFunctionInfo> shared_info(function_->shared()); - Handle<ScopeInfo> scope_info(shared_info->scope_info()); - if (shared_info->script() == isolate->heap()->undefined_value()) { - while (context_->closure() == *function_) { - context_ = Handle<Context>(context_->previous(), isolate_); - } - return; - } - - // Get the debug info (create it if it does not exist). - if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) { - // Return if ensuring debug info failed. - return; - } - - // Currently it takes too much time to find nested scopes due to script - // parsing. Sometimes we want to run the ScopeIterator as fast as possible - // (for example, while collecting async call stacks on every - // addEventListener call), even if we drop some nested scopes. - // Later we may optimize getting the nested scopes (cache the result?) - // and include nested scopes into the "fast" iteration case as well. - if (!ignore_nested_scopes) { - Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info); - - // PC points to the instruction after the current one, possibly a break - // location as well. So the "- 1" to exclude it from the search. - Address call_pc = frame->pc() - 1; - - // Find the break point where execution has stopped. - BreakLocation location = - BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); - - // Within the return sequence at the moment it is not possible to - // get a source position which is consistent with the current scope chain. - // Thus all nested with, catch and block contexts are skipped and we only - // provide the function scope. - ignore_nested_scopes = location.IsExit(); - } - - if (ignore_nested_scopes) { - if (scope_info->HasContext()) { - context_ = Handle<Context>(context_->declaration_context(), isolate_); - } else { - while (context_->closure() == *function_) { - context_ = Handle<Context>(context_->previous(), isolate_); - } - } - if (scope_info->scope_type() == FUNCTION_SCOPE || - scope_info->scope_type() == ARROW_SCOPE) { - nested_scope_chain_.Add(scope_info); - } - } else { - // Reparse the code and analyze the scopes. - Handle<Script> script(Script::cast(shared_info->script())); - Scope* scope = NULL; - - // Check whether we are in global, eval or function code. - Handle<ScopeInfo> scope_info(shared_info->scope_info()); - Zone zone; - if (scope_info->scope_type() != FUNCTION_SCOPE && - scope_info->scope_type() != ARROW_SCOPE) { - // Global or eval code. - ParseInfo info(&zone, script); - if (scope_info->scope_type() == SCRIPT_SCOPE) { - info.set_global(); - } else { - DCHECK(scope_info->scope_type() == EVAL_SCOPE); - info.set_eval(); - info.set_context(Handle<Context>(function_->context())); - } - if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) { - scope = info.function()->scope(); - } - RetrieveScopeChain(scope, shared_info); - } else { - // Function code - ParseInfo info(&zone, function_); - if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) { - scope = info.function()->scope(); - } - RetrieveScopeChain(scope, shared_info); - } - } - } - - ScopeIterator(Isolate* isolate, Handle<JSFunction> function) - : isolate_(isolate), - frame_(NULL), - inlined_jsframe_index_(0), - function_(function), - context_(function->context()), - seen_script_scope_(false), - failed_(false) { - if (function->IsBuiltin()) { - context_ = Handle<Context>(); - } - } - - // More scopes? - bool Done() { - DCHECK(!failed_); - return context_.is_null(); - } - - bool Failed() { return failed_; } - - // Move to the next scope. - void Next() { - DCHECK(!failed_); - ScopeType scope_type = Type(); - if (scope_type == ScopeTypeGlobal) { - // The global scope is always the last in the chain. - DCHECK(context_->IsNativeContext()); - context_ = Handle<Context>(); - return; - } - if (scope_type == ScopeTypeScript) { - seen_script_scope_ = true; - if (context_->IsScriptContext()) { - context_ = Handle<Context>(context_->previous(), isolate_); - } - if (!nested_scope_chain_.is_empty()) { - DCHECK_EQ(nested_scope_chain_.last()->scope_type(), SCRIPT_SCOPE); - nested_scope_chain_.RemoveLast(); - DCHECK(nested_scope_chain_.is_empty()); - } - CHECK(context_->IsNativeContext()); - return; - } - if (nested_scope_chain_.is_empty()) { - context_ = Handle<Context>(context_->previous(), isolate_); - } else { - if (nested_scope_chain_.last()->HasContext()) { - DCHECK(context_->previous() != NULL); - context_ = Handle<Context>(context_->previous(), isolate_); - } - nested_scope_chain_.RemoveLast(); - } - } - - // Return the type of the current scope. - ScopeType Type() { - DCHECK(!failed_); - if (!nested_scope_chain_.is_empty()) { - Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); - switch (scope_info->scope_type()) { - case FUNCTION_SCOPE: - case ARROW_SCOPE: - DCHECK(context_->IsFunctionContext() || !scope_info->HasContext()); - return ScopeTypeLocal; - case MODULE_SCOPE: - DCHECK(context_->IsModuleContext()); - return ScopeTypeModule; - case SCRIPT_SCOPE: - DCHECK(context_->IsScriptContext() || context_->IsNativeContext()); - return ScopeTypeScript; - case WITH_SCOPE: - DCHECK(context_->IsWithContext()); - return ScopeTypeWith; - case CATCH_SCOPE: - DCHECK(context_->IsCatchContext()); - return ScopeTypeCatch; - case BLOCK_SCOPE: - DCHECK(!scope_info->HasContext() || context_->IsBlockContext()); - return ScopeTypeBlock; - case EVAL_SCOPE: - UNREACHABLE(); - } - } - if (context_->IsNativeContext()) { - DCHECK(context_->global_object()->IsGlobalObject()); - // If we are at the native context and have not yet seen script scope, - // fake it. - return seen_script_scope_ ? ScopeTypeGlobal : ScopeTypeScript; - } - if (context_->IsFunctionContext()) { - return ScopeTypeClosure; - } - if (context_->IsCatchContext()) { - return ScopeTypeCatch; - } - if (context_->IsBlockContext()) { - return ScopeTypeBlock; - } - if (context_->IsModuleContext()) { - return ScopeTypeModule; - } - if (context_->IsScriptContext()) { - return ScopeTypeScript; - } - DCHECK(context_->IsWithContext()); - return ScopeTypeWith; - } - - // Return the JavaScript object with the content of the current scope. - MaybeHandle<JSObject> ScopeObject() { - DCHECK(!failed_); - switch (Type()) { - case ScopeIterator::ScopeTypeGlobal: - return Handle<JSObject>(CurrentContext()->global_object()); - case ScopeIterator::ScopeTypeScript: - return MaterializeScriptScope( - Handle<GlobalObject>(CurrentContext()->global_object())); - case ScopeIterator::ScopeTypeLocal: - // Materialize the content of the local scope into a JSObject. - DCHECK(nested_scope_chain_.length() == 1); - return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_); - case ScopeIterator::ScopeTypeWith: - // Return the with object. - return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); - case ScopeIterator::ScopeTypeCatch: - return MaterializeCatchScope(isolate_, CurrentContext()); - case ScopeIterator::ScopeTypeClosure: - // Materialize the content of the closure scope into a JSObject. - return MaterializeClosure(isolate_, CurrentContext()); - case ScopeIterator::ScopeTypeBlock: { - if (!nested_scope_chain_.is_empty()) { - // this is a block scope on the stack. - Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); - Handle<Context> context = scope_info->HasContext() - ? CurrentContext() - : Handle<Context>::null(); - return MaterializeBlockScope(isolate_, scope_info, context, frame_, - inlined_jsframe_index_); - } else { - return MaterializeBlockScope(isolate_, Handle<ScopeInfo>::null(), - CurrentContext(), nullptr, 0); - } - } - case ScopeIterator::ScopeTypeModule: - return MaterializeModuleScope(isolate_, CurrentContext()); - } - UNREACHABLE(); - return Handle<JSObject>(); - } - - bool HasContext() { - ScopeType type = Type(); - if (type == ScopeTypeBlock || type == ScopeTypeLocal) { - if (!nested_scope_chain_.is_empty()) { - return nested_scope_chain_.last()->HasContext(); - } - } - return true; - } - - bool SetVariableValue(Handle<String> variable_name, - Handle<Object> new_value) { - DCHECK(!failed_); - switch (Type()) { - case ScopeIterator::ScopeTypeGlobal: - break; - case ScopeIterator::ScopeTypeLocal: - return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_, - variable_name, new_value); - case ScopeIterator::ScopeTypeWith: - break; - case ScopeIterator::ScopeTypeCatch: - return SetCatchVariableValue(isolate_, CurrentContext(), variable_name, - new_value); - case ScopeIterator::ScopeTypeClosure: - return SetClosureVariableValue(isolate_, CurrentContext(), - variable_name, new_value); - case ScopeIterator::ScopeTypeScript: - return SetScriptVariableValue(CurrentContext(), variable_name, - new_value); - case ScopeIterator::ScopeTypeBlock: - return SetBlockVariableValue( - isolate_, HasContext() ? CurrentContext() : Handle<Context>::null(), - CurrentScopeInfo(), frame_, variable_name, new_value); - case ScopeIterator::ScopeTypeModule: - // TODO(2399): should we implement it? - break; - } - return false; - } - - Handle<ScopeInfo> CurrentScopeInfo() { - DCHECK(!failed_); - if (!nested_scope_chain_.is_empty()) { - return nested_scope_chain_.last(); - } else if (context_->IsBlockContext()) { - return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension())); - } else if (context_->IsFunctionContext()) { - return Handle<ScopeInfo>(context_->closure()->shared()->scope_info()); - } - return Handle<ScopeInfo>::null(); - } - - // Return the context for this scope. For the local context there might not - // be an actual context. - Handle<Context> CurrentContext() { - DCHECK(!failed_); - if (Type() == ScopeTypeGlobal || Type() == ScopeTypeScript || - nested_scope_chain_.is_empty()) { - return context_; - } else if (nested_scope_chain_.last()->HasContext()) { - return context_; - } else { - return Handle<Context>(); - } - } - -#ifdef DEBUG - // Debug print of the content of the current scope. - void DebugPrint() { - OFStream os(stdout); - DCHECK(!failed_); - switch (Type()) { - case ScopeIterator::ScopeTypeGlobal: - os << "Global:\n"; - CurrentContext()->Print(os); - break; - - case ScopeIterator::ScopeTypeLocal: { - os << "Local:\n"; - function_->shared()->scope_info()->Print(); - if (!CurrentContext().is_null()) { - CurrentContext()->Print(os); - if (CurrentContext()->has_extension()) { - Handle<Object> extension(CurrentContext()->extension(), isolate_); - if (extension->IsJSContextExtensionObject()) { - extension->Print(os); - } - } - } - break; - } - - case ScopeIterator::ScopeTypeWith: - os << "With:\n"; - CurrentContext()->extension()->Print(os); - break; - - case ScopeIterator::ScopeTypeCatch: - os << "Catch:\n"; - CurrentContext()->extension()->Print(os); - CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print(os); - break; - - case ScopeIterator::ScopeTypeClosure: - os << "Closure:\n"; - CurrentContext()->Print(os); - if (CurrentContext()->has_extension()) { - Handle<Object> extension(CurrentContext()->extension(), isolate_); - if (extension->IsJSContextExtensionObject()) { - extension->Print(os); - } - } - break; - - case ScopeIterator::ScopeTypeScript: - os << "Script:\n"; - CurrentContext() - ->global_object() - ->native_context() - ->script_context_table() - ->Print(os); - break; - - default: - UNREACHABLE(); - } - PrintF("\n"); - } -#endif - - private: - Isolate* isolate_; - JavaScriptFrame* frame_; - int inlined_jsframe_index_; - Handle<JSFunction> function_; - Handle<Context> context_; - List<Handle<ScopeInfo> > nested_scope_chain_; - bool seen_script_scope_; - bool failed_; - - void RetrieveScopeChain(Scope* scope, - Handle<SharedFunctionInfo> shared_info) { - if (scope != NULL) { - int source_position = shared_info->code()->SourcePosition(frame_->pc()); - scope->GetNestedScopeChain(isolate_, &nested_scope_chain_, - source_position); - } else { - // A failed reparse indicates that the preparser has diverged from the - // parser or that the preparse data given to the initial parse has been - // faulty. We fail in debug mode but in release mode we only provide the - // information we get from the context chain but nothing about - // completely stack allocated scopes or stack allocated locals. - // Or it could be due to stack overflow. - DCHECK(isolate_->has_pending_exception()); - failed_ = true; - } - } - - DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); -}; - - RUNTIME_FUNCTION(Runtime_GetScopeCount) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -1790,13 +749,14 @@ RUNTIME_FUNCTION(Runtime_GetScopeCount) { CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); // Get the frame where the debugging is performed. - StackFrame::Id id = UnwrapFrameId(wrapped_id); + StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); JavaScriptFrameIterator it(isolate, id); JavaScriptFrame* frame = it.frame(); + FrameInspector frame_inspector(frame, 0, isolate); // Count the visible scopes. int n = 0; - for (ScopeIterator it(isolate, frame, 0); !it.Done(); it.Next()) { + for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) { n++; } @@ -1816,85 +776,18 @@ RUNTIME_FUNCTION(Runtime_GetStepInPositions) { CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); // Get the frame where the debugging is performed. - StackFrame::Id id = UnwrapFrameId(wrapped_id); + StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); JavaScriptFrameIterator frame_it(isolate, id); RUNTIME_ASSERT(!frame_it.done()); - List<FrameSummary> frames(FLAG_max_inlining_levels + 1); - frame_it.frame()->Summarize(&frames); - FrameSummary summary = frames.first(); - - Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); - Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); - - if (!isolate->debug()->EnsureDebugInfo(shared, fun)) { - return isolate->heap()->undefined_value(); - } - - Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared); - - // Find range of break points starting from the break point where execution - // has stopped. - Address call_pc = summary.pc() - 1; - List<BreakLocation> locations; - BreakLocation::FromAddressSameStatement(debug_info, ALL_BREAK_LOCATIONS, - call_pc, &locations); - - Handle<JSArray> array = isolate->factory()->NewJSArray(locations.length()); - - int index = 0; - for (BreakLocation location : locations) { - bool accept; - if (location.pc() > summary.pc()) { - accept = true; - } else { - StackFrame::Id break_frame_id = isolate->debug()->break_frame_id(); - // The break point is near our pc. Could be a step-in possibility, - // that is currently taken by active debugger call. - if (break_frame_id == StackFrame::NO_ID) { - // We are not stepping. - accept = false; - } else { - JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id); - // If our frame is a top frame and we are stepping, we can do step-in - // at this place. - accept = additional_frame_it.frame()->id() == id; - } - } - if (accept) { - if (location.IsStepInLocation()) { - Smi* position_value = Smi::FromInt(location.position()); - RETURN_FAILURE_ON_EXCEPTION( - isolate, - JSObject::SetElement(array, index, handle(position_value, isolate), - SLOPPY)); - index++; - } - } + List<int> positions; + isolate->debug()->GetStepinPositions(frame_it.frame(), id, &positions); + Factory* factory = isolate->factory(); + Handle<FixedArray> array = factory->NewFixedArray(positions.length()); + for (int i = 0; i < positions.length(); ++i) { + array->set(i, Smi::FromInt(positions[i])); } - return *array; -} - - -static const int kScopeDetailsTypeIndex = 0; -static const int kScopeDetailsObjectIndex = 1; -static const int kScopeDetailsSize = 2; - - -MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScopeDetails( - Isolate* isolate, ScopeIterator* it) { - // Calculate the size of the result. - int details_size = kScopeDetailsSize; - Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); - - // Fill in scope details. - details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type())); - Handle<JSObject> scope_object; - ASSIGN_RETURN_ON_EXCEPTION(isolate, scope_object, it->ScopeObject(), - JSObject); - details->set(kScopeDetailsObjectIndex, *scope_object); - - return isolate->factory()->NewJSArrayWithElements(details); + return *factory->NewJSArrayWithElements(array, FAST_SMI_ELEMENTS); } @@ -1918,13 +811,14 @@ RUNTIME_FUNCTION(Runtime_GetScopeDetails) { CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); // Get the frame where the debugging is performed. - StackFrame::Id id = UnwrapFrameId(wrapped_id); + StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); JavaScriptFrameIterator frame_it(isolate, id); JavaScriptFrame* frame = frame_it.frame(); + FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); // Find the requested scope. int n = 0; - ScopeIterator it(isolate, frame, inlined_jsframe_index); + ScopeIterator it(isolate, &frame_inspector); for (; !it.Done() && n < index; it.Next()) { n++; } @@ -1933,7 +827,7 @@ RUNTIME_FUNCTION(Runtime_GetScopeDetails) { } Handle<JSObject> details; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, - MaterializeScopeDetails(isolate, &it)); + it.MaterializeScopeDetails()); return *details; } @@ -1963,16 +857,17 @@ RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { } // Get the frame where the debugging is performed. - StackFrame::Id id = UnwrapFrameId(wrapped_id); + StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); JavaScriptFrameIterator frame_it(isolate, id); JavaScriptFrame* frame = frame_it.frame(); + FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); List<Handle<JSObject> > result(4); - ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes); + ScopeIterator it(isolate, &frame_inspector, ignore_nested_scopes); for (; !it.Done(); it.Next()) { Handle<JSObject> details; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, - MaterializeScopeDetails(isolate, &it)); + it.MaterializeScopeDetails()); result.Add(details); } @@ -2021,7 +916,7 @@ RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) { Handle<JSObject> details; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, - MaterializeScopeDetails(isolate, &it)); + it.MaterializeScopeDetails()); return *details; } @@ -2066,11 +961,12 @@ RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) { CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); // Get the frame where the debugging is performed. - StackFrame::Id id = UnwrapFrameId(wrapped_id); + StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); JavaScriptFrameIterator frame_it(isolate, id); JavaScriptFrame* frame = frame_it.frame(); + FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); - ScopeIterator it(isolate, frame, inlined_jsframe_index); + ScopeIterator it(isolate, &frame_inspector); res = SetScopeVariableValue(&it, index, variable_name, new_value); } else { CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); @@ -2090,7 +986,9 @@ RUNTIME_FUNCTION(Runtime_DebugPrintScopes) { // Print the scopes for the top frame. StackFrameLocator locator(isolate); JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); - for (ScopeIterator it(isolate, frame, 0); !it.Done(); it.Next()) { + FrameInspector frame_inspector(frame, 0, isolate); + + for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) { it.DebugPrint(); } #endif @@ -2336,7 +1234,7 @@ RUNTIME_FUNCTION(Runtime_PrepareStep) { if (wrapped_frame_id == 0) { frame_id = StackFrame::NO_ID; } else { - frame_id = UnwrapFrameId(wrapped_frame_id); + frame_id = DebugFrameHelper::UnwrapFrameId(wrapped_frame_id); } // Get the step action and check validity. @@ -2378,254 +1276,6 @@ RUNTIME_FUNCTION(Runtime_ClearStepping) { } -// Helper function to find or create the arguments object for -// Runtime_DebugEvaluate. -static void MaterializeArgumentsObject(Isolate* isolate, - Handle<JSObject> target, - Handle<JSFunction> function) { - // Do not materialize the arguments object for eval or top-level code. - // Skip if "arguments" is already taken. - if (!function->shared()->is_function()) return; - Maybe<bool> maybe = JSReceiver::HasOwnProperty( - target, isolate->factory()->arguments_string()); - DCHECK(maybe.IsJust()); - if (maybe.FromJust()) return; - - // FunctionGetArguments can't throw an exception. - Handle<JSObject> arguments = - Handle<JSObject>::cast(Accessors::FunctionGetArguments(function)); - Handle<String> arguments_str = isolate->factory()->arguments_string(); - JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments, - NONE).Check(); -} - - -// Compile and evaluate source for the given context. -static MaybeHandle<Object> DebugEvaluate(Isolate* isolate, - Handle<SharedFunctionInfo> outer_info, - Handle<Context> context, - Handle<Object> context_extension, - Handle<Object> receiver, - Handle<String> source) { - if (context_extension->IsJSObject()) { - Handle<JSObject> extension = Handle<JSObject>::cast(context_extension); - Handle<JSFunction> closure(context->closure(), isolate); - context = isolate->factory()->NewWithContext(closure, context, extension); - } - - Handle<JSFunction> eval_fun; - ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_fun, - Compiler::GetFunctionFromEval( - source, outer_info, context, SLOPPY, - NO_PARSE_RESTRICTION, RelocInfo::kNoPosition), - Object); - - Handle<Object> result; - ASSIGN_RETURN_ON_EXCEPTION( - isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL), - Object); - - // Skip the global proxy as it has no properties and always delegates to the - // real global object. - if (result->IsJSGlobalProxy()) { - PrototypeIterator iter(isolate, result); - // TODO(verwaest): This will crash when the global proxy is detached. - result = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); - } - - return result; -} - - -static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) { - Handle<JSObject> result = - isolate->factory()->NewJSObject(isolate->object_function()); - Handle<Map> new_map = - Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto"); - Map::SetPrototype(new_map, isolate->factory()->null_value()); - JSObject::MigrateToMap(result, new_map); - return result; -} - - -namespace { - -// This class builds a context chain for evaluation of expressions -// in debugger. -// The scope chain leading up to a breakpoint where evaluation occurs -// looks like: -// - [a mix of with, catch and block scopes] -// - [function stack + context] -// - [outer context] -// The builder materializes all stack variables into properties of objects; -// the expression is then evaluated as if it is inside a series of 'with' -// statements using those objects. To this end, the builder builds a new -// context chain, based on a scope chain: -// - every With and Catch scope begets a cloned context -// - Block scope begets one or two contexts: -// - if a block has context-allocated varaibles, its context is cloned -// - stack locals are materizalized as a With context -// - Local scope begets a With context for materizalized locals, chained to -// original function context. Original function context is the end of -// the chain. -class EvaluationContextBuilder { - public: - EvaluationContextBuilder(Isolate* isolate, JavaScriptFrame* frame, - int inlined_jsframe_index) - : isolate_(isolate), - frame_(frame), - inlined_jsframe_index_(inlined_jsframe_index) { - FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); - Handle<JSFunction> function = - handle(JSFunction::cast(frame_inspector.GetFunction())); - Handle<Context> outer_context = handle(function->context(), isolate); - outer_info_ = handle(function->shared()); - Handle<Context> inner_context; - - bool stop = false; - for (ScopeIterator it(isolate, frame, inlined_jsframe_index); - !it.Failed() && !it.Done() && !stop; it.Next()) { - ScopeIterator::ScopeType scope_type = it.Type(); - - if (scope_type == ScopeIterator::ScopeTypeLocal) { - Handle<Context> parent_context = - it.HasContext() ? it.CurrentContext() : outer_context; - - // The "this" binding, if any, can't be bound via "with". If we need - // to, add another node onto the outer context to bind "this". - parent_context = - MaterializeReceiver(isolate, parent_context, function, frame); - - Handle<JSObject> materialized_function = - NewJSObjectWithNullProto(isolate); - - MaterializeStackLocalsWithFrameInspector(isolate, materialized_function, - function, &frame_inspector); - - MaterializeArgumentsObject(isolate, materialized_function, function); - - Handle<Context> with_context = isolate->factory()->NewWithContext( - function, parent_context, materialized_function); - - ContextChainElement context_chain_element; - context_chain_element.original_context = it.CurrentContext(); - context_chain_element.materialized_object = materialized_function; - context_chain_element.scope_info = it.CurrentScopeInfo(); - context_chain_.Add(context_chain_element); - - stop = true; - RecordContextsInChain(&inner_context, with_context, with_context); - } else if (scope_type == ScopeIterator::ScopeTypeCatch || - scope_type == ScopeIterator::ScopeTypeWith) { - Handle<Context> cloned_context = - Handle<Context>::cast(FixedArray::CopySize( - it.CurrentContext(), it.CurrentContext()->length())); - - ContextChainElement context_chain_element; - context_chain_element.original_context = it.CurrentContext(); - context_chain_element.cloned_context = cloned_context; - context_chain_.Add(context_chain_element); - - RecordContextsInChain(&inner_context, cloned_context, cloned_context); - } else if (scope_type == ScopeIterator::ScopeTypeBlock) { - Handle<JSObject> materialized_object = - NewJSObjectWithNullProto(isolate); - MaterializeStackLocalsWithFrameInspector(isolate, materialized_object, - it.CurrentScopeInfo(), - &frame_inspector); - if (it.HasContext()) { - Handle<Context> cloned_context = - Handle<Context>::cast(FixedArray::CopySize( - it.CurrentContext(), it.CurrentContext()->length())); - Handle<Context> with_context = isolate->factory()->NewWithContext( - function, cloned_context, materialized_object); - - ContextChainElement context_chain_element; - context_chain_element.original_context = it.CurrentContext(); - context_chain_element.cloned_context = cloned_context; - context_chain_element.materialized_object = materialized_object; - context_chain_element.scope_info = it.CurrentScopeInfo(); - context_chain_.Add(context_chain_element); - - RecordContextsInChain(&inner_context, cloned_context, with_context); - } else { - Handle<Context> with_context = isolate->factory()->NewWithContext( - function, outer_context, materialized_object); - - ContextChainElement context_chain_element; - context_chain_element.materialized_object = materialized_object; - context_chain_element.scope_info = it.CurrentScopeInfo(); - context_chain_.Add(context_chain_element); - - RecordContextsInChain(&inner_context, with_context, with_context); - } - } else { - stop = true; - } - } - if (innermost_context_.is_null()) { - innermost_context_ = outer_context; - } - DCHECK(!innermost_context_.is_null()); - } - - void UpdateVariables() { - for (int i = 0; i < context_chain_.length(); i++) { - ContextChainElement element = context_chain_[i]; - if (!element.original_context.is_null() && - !element.cloned_context.is_null()) { - Handle<Context> cloned_context = element.cloned_context; - cloned_context->CopyTo( - Context::MIN_CONTEXT_SLOTS, *element.original_context, - Context::MIN_CONTEXT_SLOTS, - cloned_context->length() - Context::MIN_CONTEXT_SLOTS); - } - if (!element.materialized_object.is_null()) { - // Write back potential changes to materialized stack locals to the - // stack. - UpdateStackLocalsFromMaterializedObject( - isolate_, element.materialized_object, element.scope_info, frame_, - inlined_jsframe_index_); - } - } - } - - Handle<Context> innermost_context() const { return innermost_context_; } - Handle<SharedFunctionInfo> outer_info() const { return outer_info_; } - - private: - struct ContextChainElement { - Handle<Context> original_context; - Handle<Context> cloned_context; - Handle<JSObject> materialized_object; - Handle<ScopeInfo> scope_info; - }; - - void RecordContextsInChain(Handle<Context>* inner_context, - Handle<Context> first, Handle<Context> last) { - if (!inner_context->is_null()) { - (*inner_context)->set_previous(*last); - } else { - innermost_context_ = last; - } - *inner_context = first; - } - - Handle<SharedFunctionInfo> outer_info_; - Handle<Context> innermost_context_; - List<ContextChainElement> context_chain_; - Isolate* isolate_; - JavaScriptFrame* frame_; - int inlined_jsframe_index_; -}; -} - - -// Evaluate a piece of JavaScript in the context of a stack frame for -// debugging. Things that need special attention are: -// - Parameters and stack-allocated locals need to be materialized. Altered -// values need to be written back to the stack afterwards. -// - The arguments object needs to materialized. RUNTIME_FUNCTION(Runtime_DebugEvaluate) { HandleScope scope(isolate); @@ -2641,50 +1291,17 @@ RUNTIME_FUNCTION(Runtime_DebugEvaluate) { CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4); CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5); - // Handle the processing of break. - DisableBreak disable_break_scope(isolate->debug(), disable_break); - - // Get the frame where the debugging is performed. - StackFrame::Id id = UnwrapFrameId(wrapped_id); - JavaScriptFrameIterator it(isolate, id); - JavaScriptFrame* frame = it.frame(); - - // Traverse the saved contexts chain to find the active context for the - // selected frame. - SaveContext* save = FindSavedContextForFrame(isolate, frame); - - SaveContext savex(isolate); - isolate->set_context(*(save->context())); - - // Materialize stack locals and the arguments object. - - EvaluationContextBuilder context_builder(isolate, frame, - inlined_jsframe_index); - if (isolate->has_pending_exception()) { - return isolate->heap()->exception(); - } - - - Handle<Object> receiver(frame->receiver(), isolate); - MaybeHandle<Object> maybe_result = DebugEvaluate( - isolate, context_builder.outer_info(), - context_builder.innermost_context(), context_extension, receiver, source); + StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); - context_builder.UpdateVariables(); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, + DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source, + disable_break, context_extension)); return *result; } -static inline bool IsDebugContext(Isolate* isolate, Context* context) { - // Try to unwrap script context if it exist. - if (context->IsScriptContext()) context = context->previous(); - DCHECK_NOT_NULL(context); - return context == *isolate->debug()->debug_context(); -} - - RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { HandleScope scope(isolate); @@ -2698,28 +1315,10 @@ RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2); CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3); - // Handle the processing of break. - DisableBreak disable_break_scope(isolate->debug(), disable_break); - - // Enter the top context from before the debugger was invoked. - SaveContext save(isolate); - SaveContext* top = &save; - while (top != NULL && IsDebugContext(isolate, *top->context())) { - top = top->prev(); - } - if (top != NULL) { - isolate->set_context(*top->context()); - } - - // Get the native context now set to the top context from before the - // debugger was invoked. - Handle<Context> context = isolate->native_context(); - Handle<JSObject> receiver(context->global_proxy()); - Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate); Handle<Object> result; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, DebugEvaluate(isolate, outer_info, context, - context_extension, receiver, source)); + isolate, result, + DebugEvaluate::Global(isolate, source, disable_break, context_extension)); return *result; } @@ -2760,71 +1359,6 @@ RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) { } -// Helper function used by Runtime_DebugReferencedBy below. -static int DebugReferencedBy(HeapIterator* iterator, JSObject* target, - Object* instance_filter, int max_references, - FixedArray* instances, int instances_size, - JSFunction* arguments_function) { - Isolate* isolate = target->GetIsolate(); - SealHandleScope shs(isolate); - DisallowHeapAllocation no_allocation; - - // Iterate the heap. - int count = 0; - JSObject* last = NULL; - HeapObject* heap_obj = NULL; - while (((heap_obj = iterator->next()) != NULL) && - (max_references == 0 || count < max_references)) { - // Only look at all JSObjects. - if (heap_obj->IsJSObject()) { - // Skip context extension objects and argument arrays as these are - // checked in the context of functions using them. - JSObject* obj = JSObject::cast(heap_obj); - if (obj->IsJSContextExtensionObject() || - obj->map()->GetConstructor() == arguments_function) { - continue; - } - - // Check if the JS object has a reference to the object looked for. - if (obj->ReferencesObject(target)) { - // Check instance filter if supplied. This is normally used to avoid - // references from mirror objects (see Runtime_IsInPrototypeChain). - if (!instance_filter->IsUndefined()) { - for (PrototypeIterator iter(isolate, obj); !iter.IsAtEnd(); - iter.Advance()) { - if (iter.GetCurrent() == instance_filter) { - obj = NULL; // Don't add this object. - break; - } - } - } - - if (obj != NULL) { - // Valid reference found add to instance array if supplied an update - // count. - if (instances != NULL && count < instances_size) { - instances->set(count, obj); - } - last = obj; - count++; - } - } - } - } - - // Check for circular reference only. This can happen when the object is only - // referenced from mirrors and has a circular reference in which case the - // object is not really alive and would have been garbage collected if not - // referenced from the mirror. - if (count == 1 && last == target) { - count = 0; - } - - // Return the number of referencing objects found. - return count; -} - - // Scan the heap for objects with direct references to an object // args[0]: the object to find references to // args[1]: constructor function for instances to exclude (Mirror) @@ -2832,79 +1366,54 @@ static int DebugReferencedBy(HeapIterator* iterator, JSObject* target, RUNTIME_FUNCTION(Runtime_DebugReferencedBy) { HandleScope scope(isolate); DCHECK(args.length() == 3); - - // Check parameters. CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1); - RUNTIME_ASSERT(instance_filter->IsUndefined() || - instance_filter->IsJSObject()); + CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1); + RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject()); CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); RUNTIME_ASSERT(max_references >= 0); - - // Get the constructor function for context extension and arguments array. - Handle<JSFunction> arguments_function( - JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); - - // Get the number of referencing objects. - int count; - // First perform a full GC in order to avoid dead objects and to make the heap - // iterable. + List<Handle<JSObject> > instances; Heap* heap = isolate->heap(); - heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy"); - { - HeapIterator heap_iterator(heap); - count = DebugReferencedBy(&heap_iterator, *target, *instance_filter, - max_references, NULL, 0, *arguments_function); - } - - // Allocate an array to hold the result. - Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count); - - // Fill the referencing objects. { - HeapIterator heap_iterator(heap); - count = DebugReferencedBy(&heap_iterator, *target, *instance_filter, - max_references, *instances, count, - *arguments_function); - } - - // Return result as JS array. - Handle<JSFunction> constructor = isolate->array_function(); - - Handle<JSObject> result = isolate->factory()->NewJSObject(constructor); - JSArray::SetContent(Handle<JSArray>::cast(result), instances); - return *result; -} - - -// Helper function used by Runtime_DebugConstructedBy below. -static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor, - int max_references, FixedArray* instances, - int instances_size) { - DisallowHeapAllocation no_allocation; - - // Iterate the heap. - int count = 0; - HeapObject* heap_obj = NULL; - while (((heap_obj = iterator->next()) != NULL) && - (max_references == 0 || count < max_references)) { - // Only look at all JSObjects. - if (heap_obj->IsJSObject()) { + HeapIterator iterator(heap, HeapIterator::kFilterUnreachable); + // Get the constructor function for context extension and arguments array. + Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor(); + HeapObject* heap_obj; + while ((heap_obj = iterator.next())) { + if (!heap_obj->IsJSObject()) continue; JSObject* obj = JSObject::cast(heap_obj); - if (obj->map()->GetConstructor() == constructor) { - // Valid reference found add to instance array if supplied an update - // count. - if (instances != NULL && count < instances_size) { - instances->set(count, obj); - } - count++; + if (obj->IsJSContextExtensionObject()) continue; + if (obj->map()->GetConstructor() == arguments_fun) continue; + if (!obj->ReferencesObject(*target)) continue; + // Check filter if supplied. This is normally used to avoid + // references from mirror objects. + if (!filter->IsUndefined() && + obj->HasInPrototypeChain(isolate, *filter)) { + continue; + } + if (obj->IsJSGlobalObject()) { + obj = JSGlobalObject::cast(obj)->global_proxy(); } + instances.Add(Handle<JSObject>(obj)); + if (instances.length() == max_references) break; + } + // Iterate the rest of the heap to satisfy HeapIterator constraints. + while (iterator.next()) { } } - // Return the number of referencing objects found. - return count; + Handle<FixedArray> result; + if (instances.length() == 1 && instances.last().is_identical_to(target)) { + // Check for circular reference only. This can happen when the object is + // only referenced from mirrors and has a circular reference in which case + // the object is not really alive and would have been garbage collected if + // not referenced from the mirror. + result = isolate->factory()->empty_fixed_array(); + } else { + result = isolate->factory()->NewFixedArray(instances.length()); + for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]); + } + return *isolate->factory()->NewJSArrayWithElements(result); } @@ -2914,40 +1423,31 @@ static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor, RUNTIME_FUNCTION(Runtime_DebugConstructedBy) { HandleScope scope(isolate); DCHECK(args.length() == 2); - - - // Check parameters. CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); RUNTIME_ASSERT(max_references >= 0); - // Get the number of referencing objects. - int count; - // First perform a full GC in order to avoid dead objects and to make the heap - // iterable. + List<Handle<JSObject> > instances; Heap* heap = isolate->heap(); - heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy"); - { - HeapIterator heap_iterator(heap); - count = DebugConstructedBy(&heap_iterator, *constructor, max_references, - NULL, 0); - } - - // Allocate an array to hold the result. - Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count); - - // Fill the referencing objects. { - HeapIterator heap_iterator2(heap); - count = DebugConstructedBy(&heap_iterator2, *constructor, max_references, - *instances, count); + HeapIterator iterator(heap, HeapIterator::kFilterUnreachable); + HeapObject* heap_obj; + while ((heap_obj = iterator.next())) { + if (!heap_obj->IsJSObject()) continue; + JSObject* obj = JSObject::cast(heap_obj); + if (obj->map()->GetConstructor() != *constructor) continue; + instances.Add(Handle<JSObject>(obj)); + if (instances.length() == max_references) break; + } + // Iterate the rest of the heap to satisfy HeapIterator constraints. + while (iterator.next()) { + } } - // Return result as JS array. - Handle<JSFunction> array_function = isolate->array_function(); - Handle<JSObject> result = isolate->factory()->NewJSObject(array_function); - JSArray::SetContent(Handle<JSArray>::cast(result), instances); - return *result; + Handle<FixedArray> result = + isolate->factory()->NewFixedArray(instances.length()); + for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]); + return *isolate->factory()->NewJSArrayWithElements(result); } diff --git a/deps/v8/src/runtime/runtime-forin.cc b/deps/v8/src/runtime/runtime-forin.cc index c793e88b92..ecd55d172a 100644 --- a/deps/v8/src/runtime/runtime-forin.cc +++ b/deps/v8/src/runtime/runtime-forin.cc @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/arguments.h" #include "src/runtime/runtime-utils.h" -#include "src/v8.h" + +#include "src/arguments.h" +#include "src/objects-inl.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime-function.cc b/deps/v8/src/runtime/runtime-function.cc index 749e16b9ed..a368f1b14c 100644 --- a/deps/v8/src/runtime/runtime-function.cc +++ b/deps/v8/src/runtime/runtime-function.cc @@ -2,16 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/accessors.h" #include "src/arguments.h" #include "src/compiler.h" #include "src/cpu-profiler.h" #include "src/deoptimizer.h" -#include "src/frames.h" +#include "src/frames-inl.h" #include "src/messages.h" -#include "src/runtime/runtime-utils.h" namespace v8 { namespace internal { @@ -328,9 +327,8 @@ RUNTIME_FUNCTION(Runtime_SetForceInlineFlag) { // Find the arguments of the JavaScript function invocation that called // into C++ code. Collect these in a newly allocated array of handles (possibly // prefixed by a number of empty handles). -static SmartArrayPointer<Handle<Object> > GetCallerArguments(Isolate* isolate, - int prefix_argc, - int* total_argc) { +static base::SmartArrayPointer<Handle<Object> > GetCallerArguments( + Isolate* isolate, int prefix_argc, int* total_argc) { // Find frame containing arguments passed to the caller. JavaScriptFrameIterator it(isolate); JavaScriptFrame* frame = it.frame(); @@ -355,7 +353,7 @@ static SmartArrayPointer<Handle<Object> > GetCallerArguments(Isolate* isolate, argument_count--; *total_argc = prefix_argc + argument_count; - SmartArrayPointer<Handle<Object> > param_data( + base::SmartArrayPointer<Handle<Object> > param_data( NewArray<Handle<Object> >(*total_argc)); bool should_deoptimize = false; for (int i = 0; i < argument_count; i++) { @@ -376,7 +374,7 @@ static SmartArrayPointer<Handle<Object> > GetCallerArguments(Isolate* isolate, int args_count = frame->ComputeParametersCount(); *total_argc = prefix_argc + args_count; - SmartArrayPointer<Handle<Object> > param_data( + base::SmartArrayPointer<Handle<Object> > param_data( NewArray<Handle<Object> >(*total_argc)); for (int i = 0; i < args_count; i++) { Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); @@ -401,7 +399,7 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { bound_function->shared()->set_inferred_name(isolate->heap()->empty_string()); // Get all arguments of calling function (Function.prototype.bind). int argc = 0; - SmartArrayPointer<Handle<Object> > arguments = + base::SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(isolate, 0, &argc); // Don't count the this-arg. if (argc > 0) { @@ -443,9 +441,18 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { // Update length. Have to remove the prototype first so that map migration // is happy about the number of fields. RUNTIME_ASSERT(bound_function->RemovePrototype()); + + // The new function should have the same [[Prototype]] as the bindee. Handle<Map> bound_function_map( isolate->native_context()->bound_function_map()); + PrototypeIterator iter(isolate, bindee); + Handle<Object> proto = PrototypeIterator::GetCurrent(iter); + if (bound_function_map->prototype() != *proto) { + bound_function_map = Map::TransitionToPrototype(bound_function_map, proto, + REGULAR_PROTOTYPE); + } JSObject::MigrateToMap(bound_function, bound_function_map); + Handle<String> length_string = isolate->factory()->length_string(); // These attributes must be kept in sync with how the bootstrapper // configures the bound_function_map retrieved above. @@ -494,7 +501,7 @@ RUNTIME_FUNCTION(Runtime_NewObjectFromBound) { !Handle<JSFunction>::cast(bound_function)->shared()->bound()); int total_argc = 0; - SmartArrayPointer<Handle<Object> > param_data = + base::SmartArrayPointer<Handle<Object> > param_data = GetCallerArguments(isolate, bound_argc, &total_argc); for (int i = 0; i < bound_argc; i++) { param_data[i] = Handle<Object>( @@ -526,12 +533,12 @@ RUNTIME_FUNCTION(Runtime_Call) { // If there are too many arguments, allocate argv via malloc. const int argv_small_size = 10; Handle<Object> argv_small_buffer[argv_small_size]; - SmartArrayPointer<Handle<Object> > argv_large_buffer; + base::SmartArrayPointer<Handle<Object> > argv_large_buffer; Handle<Object>* argv = argv_small_buffer; if (argc > argv_small_size) { argv = new Handle<Object>[argc]; if (argv == NULL) return isolate->StackOverflow(); - argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv); + argv_large_buffer = base::SmartArrayPointer<Handle<Object> >(argv); } for (int i = 0; i < argc; ++i) { @@ -565,12 +572,12 @@ RUNTIME_FUNCTION(Runtime_Apply) { // If there are too many arguments, allocate argv via malloc. const int argv_small_size = 10; Handle<Object> argv_small_buffer[argv_small_size]; - SmartArrayPointer<Handle<Object> > argv_large_buffer; + base::SmartArrayPointer<Handle<Object> > argv_large_buffer; Handle<Object>* argv = argv_small_buffer; if (argc > argv_small_size) { argv = new Handle<Object>[argc]; if (argv == NULL) return isolate->StackOverflow(); - argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv); + argv_large_buffer = base::SmartArrayPointer<Handle<Object> >(argv); } for (int i = 0; i < argc; ++i) { diff --git a/deps/v8/src/runtime/runtime-futex.cc b/deps/v8/src/runtime/runtime-futex.cc new file mode 100644 index 0000000000..a96758d9f3 --- /dev/null +++ b/deps/v8/src/runtime/runtime-futex.cc @@ -0,0 +1,93 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/runtime/runtime-utils.h" + +#include "src/arguments.h" +#include "src/base/platform/time.h" +#include "src/conversions-inl.h" +#include "src/futex-emulation.h" +#include "src/globals.h" + +// Implement Futex API for SharedArrayBuffers as defined in the +// SharedArrayBuffer draft spec, found here: +// https://github.com/lars-t-hansen/ecmascript_sharedmem + +namespace v8 { +namespace internal { + +RUNTIME_FUNCTION(Runtime_AtomicsFutexWait) { + HandleScope scope(isolate); + DCHECK(args.length() == 4); + CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); + CONVERT_SIZE_ARG_CHECKED(index, 1); + CONVERT_INT32_ARG_CHECKED(value, 2); + CONVERT_DOUBLE_ARG_CHECKED(timeout, 3); + RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); + RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); + RUNTIME_ASSERT(sta->type() == kExternalInt32Array); + RUNTIME_ASSERT(timeout == V8_INFINITY || !std::isnan(timeout)); + + Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); + size_t addr = index << 2; + + return FutexEmulation::Wait(isolate, array_buffer, addr, value, timeout); +} + + +RUNTIME_FUNCTION(Runtime_AtomicsFutexWake) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); + CONVERT_SIZE_ARG_CHECKED(index, 1); + CONVERT_INT32_ARG_CHECKED(count, 2); + RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); + RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); + RUNTIME_ASSERT(sta->type() == kExternalInt32Array); + + Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); + size_t addr = index << 2; + + return FutexEmulation::Wake(isolate, array_buffer, addr, count); +} + + +RUNTIME_FUNCTION(Runtime_AtomicsFutexWakeOrRequeue) { + HandleScope scope(isolate); + DCHECK(args.length() == 5); + CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); + CONVERT_SIZE_ARG_CHECKED(index1, 1); + CONVERT_INT32_ARG_CHECKED(count, 2); + CONVERT_INT32_ARG_CHECKED(value, 3); + CONVERT_SIZE_ARG_CHECKED(index2, 4); + RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); + RUNTIME_ASSERT(index1 < NumberToSize(isolate, sta->length())); + RUNTIME_ASSERT(index2 < NumberToSize(isolate, sta->length())); + RUNTIME_ASSERT(sta->type() == kExternalInt32Array); + + Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); + size_t addr1 = index1 << 2; + size_t addr2 = index2 << 2; + + return FutexEmulation::WakeOrRequeue(isolate, array_buffer, addr1, count, + value, addr2); +} + + +RUNTIME_FUNCTION(Runtime_AtomicsFutexNumWaitersForTesting) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); + CONVERT_SIZE_ARG_CHECKED(index, 1); + RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); + RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); + RUNTIME_ASSERT(sta->type() == kExternalInt32Array); + + Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); + size_t addr = index << 2; + + return FutexEmulation::NumWaitersForTesting(isolate, array_buffer, addr); +} +} +} // namespace v8::internal diff --git a/deps/v8/src/runtime/runtime-generator.cc b/deps/v8/src/runtime/runtime-generator.cc index ed86c4dd74..208f7f6680 100644 --- a/deps/v8/src/runtime/runtime-generator.cc +++ b/deps/v8/src/runtime/runtime-generator.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" +#include "src/factory.h" #include "src/frames-inl.h" -#include "src/runtime/runtime-utils.h" +#include "src/objects-inl.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime-i18n.cc b/deps/v8/src/runtime/runtime-i18n.cc index 3da71a98ef..73d511074a 100644 --- a/deps/v8/src/runtime/runtime-i18n.cc +++ b/deps/v8/src/runtime/runtime-i18n.cc @@ -4,13 +4,14 @@ #ifdef V8_I18N_SUPPORT -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" +#include "src/api.h" #include "src/api-natives.h" #include "src/arguments.h" +#include "src/factory.h" #include "src/i18n.h" #include "src/messages.h" -#include "src/runtime/runtime-utils.h" #include "unicode/brkiter.h" #include "unicode/calendar.h" diff --git a/deps/v8/src/runtime/runtime-internal.cc b/deps/v8/src/runtime/runtime-internal.cc index 290d7af2fa..01e3e913af 100644 --- a/deps/v8/src/runtime/runtime-internal.cc +++ b/deps/v8/src/runtime/runtime-internal.cc @@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/bootstrapper.h" -#include "src/debug.h" +#include "src/conversions.h" +#include "src/debug/debug.h" +#include "src/frames-inl.h" #include "src/messages.h" #include "src/parser.h" #include "src/prettyprinter.h" -#include "src/runtime/runtime-utils.h" namespace v8 { namespace internal { @@ -23,6 +24,36 @@ RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) { } +RUNTIME_FUNCTION(Runtime_ImportToRuntime) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0); + RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); + Bootstrapper::ImportNatives(isolate, container); + return isolate->heap()->undefined_value(); +} + + +RUNTIME_FUNCTION(Runtime_ImportExperimentalToRuntime) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0); + RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); + Bootstrapper::ImportExperimentalNatives(isolate, container); + return isolate->heap()->undefined_value(); +} + + +RUNTIME_FUNCTION(Runtime_InstallJSBuiltins) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0); + RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); + Bootstrapper::InstallJSBuiltins(isolate, container); + return isolate->heap()->undefined_value(); +} + + RUNTIME_FUNCTION(Runtime_Throw) { HandleScope scope(isolate); DCHECK(args.length() == 1); @@ -222,116 +253,21 @@ RUNTIME_FUNCTION(Runtime_RenderCallSite) { if (location.start_pos() == -1) return isolate->heap()->empty_string(); Zone zone; - SmartPointer<ParseInfo> info(location.function()->shared()->is_function() - ? new ParseInfo(&zone, location.function()) - : new ParseInfo(&zone, location.script())); + base::SmartPointer<ParseInfo> info( + location.function()->shared()->is_function() + ? new ParseInfo(&zone, location.function()) + : new ParseInfo(&zone, location.script())); if (!Parser::ParseStatic(info.get())) { isolate->clear_pending_exception(); return isolate->heap()->empty_string(); } CallPrinter printer(isolate, &zone); - const char* string = printer.Print(info->function(), location.start_pos()); + const char* string = printer.Print(info->literal(), location.start_pos()); return *isolate->factory()->NewStringFromAsciiChecked(string); } -RUNTIME_FUNCTION(Runtime_GetFromCacheRT) { - SealHandleScope shs(isolate); - // This is only called from codegen, so checks might be more lax. - CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0); - CONVERT_ARG_CHECKED(Object, key, 1); - - { - DisallowHeapAllocation no_alloc; - - int finger_index = cache->finger_index(); - Object* o = cache->get(finger_index); - if (o == key) { - // The fastest case: hit the same place again. - return cache->get(finger_index + 1); - } - - for (int i = finger_index - 2; i >= JSFunctionResultCache::kEntriesIndex; - i -= 2) { - o = cache->get(i); - if (o == key) { - cache->set_finger_index(i); - return cache->get(i + 1); - } - } - - int size = cache->size(); - DCHECK(size <= cache->length()); - - for (int i = size - 2; i > finger_index; i -= 2) { - o = cache->get(i); - if (o == key) { - cache->set_finger_index(i); - return cache->get(i + 1); - } - } - } - - // There is no value in the cache. Invoke the function and cache result. - HandleScope scope(isolate); - - Handle<JSFunctionResultCache> cache_handle(cache); - Handle<Object> key_handle(key, isolate); - Handle<Object> value; - { - Handle<JSFunction> factory(JSFunction::cast( - cache_handle->get(JSFunctionResultCache::kFactoryIndex))); - // TODO(antonm): consider passing a receiver when constructing a cache. - Handle<JSObject> receiver(isolate->global_proxy()); - // This handle is nor shared, nor used later, so it's safe. - Handle<Object> argv[] = {key_handle}; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, value, - Execution::Call(isolate, factory, receiver, arraysize(argv), argv)); - } - -#ifdef VERIFY_HEAP - if (FLAG_verify_heap) { - cache_handle->JSFunctionResultCacheVerify(); - } -#endif - - // Function invocation may have cleared the cache. Reread all the data. - int finger_index = cache_handle->finger_index(); - int size = cache_handle->size(); - - // If we have spare room, put new data into it, otherwise evict post finger - // entry which is likely to be the least recently used. - int index = -1; - if (size < cache_handle->length()) { - cache_handle->set_size(size + JSFunctionResultCache::kEntrySize); - index = size; - } else { - index = finger_index + JSFunctionResultCache::kEntrySize; - if (index == cache_handle->length()) { - index = JSFunctionResultCache::kEntriesIndex; - } - } - - DCHECK(index % 2 == 0); - DCHECK(index >= JSFunctionResultCache::kEntriesIndex); - DCHECK(index < cache_handle->length()); - - cache_handle->set(index, *key_handle); - cache_handle->set(index + 1, *value); - cache_handle->set_finger_index(index); - -#ifdef VERIFY_HEAP - if (FLAG_verify_heap) { - cache_handle->JSFunctionResultCacheVerify(); - } -#endif - - return *value; -} - - RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); @@ -348,6 +284,18 @@ RUNTIME_FUNCTION(Runtime_MessageGetScript) { } +RUNTIME_FUNCTION(Runtime_ErrorToStringRT) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSObject, error, 0); + Handle<String> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, + isolate->error_tostring_helper()->Stringify(isolate, error)); + return *result; +} + + RUNTIME_FUNCTION(Runtime_FormatMessageString) { HandleScope scope(isolate); DCHECK(args.length() == 4); @@ -412,15 +360,6 @@ RUNTIME_FUNCTION(Runtime_IS_VAR) { } -RUNTIME_FUNCTION(Runtime_GetFromCache) { - HandleScope scope(isolate); - DCHECK(args.length() == 2); - CONVERT_SMI_ARG_CHECKED(id, 0); - args[0] = isolate->native_context()->jsfunction_result_caches()->get(id); - return __RT_impl_Runtime_GetFromCacheRT(args, isolate); -} - - RUNTIME_FUNCTION(Runtime_IncrementStatsCounter) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); @@ -467,5 +406,12 @@ RUNTIME_FUNCTION(Runtime_GetCallerJSFunction) { RUNTIME_ASSERT(it.frame()->type() == StackFrame::JAVA_SCRIPT); return JavaScriptFrame::cast(it.frame())->function(); } + + +RUNTIME_FUNCTION(Runtime_GetCodeStubExportsObject) { + HandleScope shs(isolate); + return isolate->heap()->code_stub_exports_object(); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-json.cc b/deps/v8/src/runtime/runtime-json.cc index 68f76c56a8..64a42bfede 100644 --- a/deps/v8/src/runtime/runtime-json.cc +++ b/deps/v8/src/runtime/runtime-json.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" +#include "src/char-predicates-inl.h" #include "src/json-parser.h" #include "src/json-stringifier.h" -#include "src/runtime/runtime-utils.h" +#include "src/objects-inl.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime-literals.cc b/deps/v8/src/runtime/runtime-literals.cc index 80af962e3c..f434747e28 100644 --- a/deps/v8/src/runtime/runtime-literals.cc +++ b/deps/v8/src/runtime/runtime-literals.cc @@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/allocation-site-scopes.h" #include "src/arguments.h" #include "src/ast.h" #include "src/parser.h" #include "src/runtime/runtime.h" -#include "src/runtime/runtime-utils.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime-liveedit.cc b/deps/v8/src/runtime/runtime-liveedit.cc index 555fb6a74b..3b8dad9b5e 100644 --- a/deps/v8/src/runtime/runtime-liveedit.cc +++ b/deps/v8/src/runtime/runtime-liveedit.cc @@ -2,43 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" -#include "src/debug.h" -#include "src/liveedit.h" +#include "src/debug/debug.h" +#include "src/debug/debug-frames.h" +#include "src/debug/liveedit.h" +#include "src/frames-inl.h" #include "src/runtime/runtime.h" -#include "src/runtime/runtime-utils.h" namespace v8 { namespace internal { - -static int FindSharedFunctionInfosForScript(HeapIterator* iterator, - Script* script, - FixedArray* buffer) { - DisallowHeapAllocation no_allocation; - int counter = 0; - int buffer_size = buffer->length(); - for (HeapObject* obj = iterator->next(); obj != NULL; - obj = iterator->next()) { - DCHECK(obj != NULL); - if (!obj->IsSharedFunctionInfo()) { - continue; - } - SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); - if (shared->script() != script) { - continue; - } - if (counter < buffer_size) { - buffer->set(counter, shared); - } - counter++; - } - return counter; -} - - // For a script finds all SharedFunctionInfo's in the heap that points // to this script. Returns JSArray of SharedFunctionInfo wrapped // in OpaqueReferences. @@ -51,32 +26,29 @@ RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) { RUNTIME_ASSERT(script_value->value()->IsScript()); Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); - const int kBufferSize = 32; - - Handle<FixedArray> array; - array = isolate->factory()->NewFixedArray(kBufferSize); - int number; + List<Handle<SharedFunctionInfo> > found; Heap* heap = isolate->heap(); { - HeapIterator heap_iterator(heap); - Script* scr = *script; - FixedArray* arr = *array; - number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); - } - if (number > kBufferSize) { - array = isolate->factory()->NewFixedArray(number); - HeapIterator heap_iterator(heap); - Script* scr = *script; - FixedArray* arr = *array; - FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); + HeapIterator iterator(heap); + HeapObject* heap_obj; + while ((heap_obj = iterator.next())) { + if (!heap_obj->IsSharedFunctionInfo()) continue; + SharedFunctionInfo* shared = SharedFunctionInfo::cast(heap_obj); + if (shared->script() != *script) continue; + found.Add(Handle<SharedFunctionInfo>(shared)); + } } - Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array); - result->set_length(Smi::FromInt(number)); - - LiveEdit::WrapSharedFunctionInfos(result); - - return *result; + Handle<FixedArray> result = isolate->factory()->NewFixedArray(found.length()); + for (int i = 0; i < found.length(); ++i) { + Handle<SharedFunctionInfo> shared = found[i]; + SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate); + Handle<String> name(String::cast(shared->name())); + info_wrapper.SetProperties(name, shared->start_position(), + shared->end_position(), shared); + result->set(i, *info_wrapper.GetJSArray()); + } + return *isolate->factory()->NewJSArrayWithElements(result); } @@ -280,7 +252,8 @@ RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) { } JavaScriptFrameIterator it(isolate, id); - int inlined_jsframe_index = Runtime::FindIndexedNonNativeFrame(&it, index); + int inlined_jsframe_index = + DebugFrameHelper::FindIndexedNonNativeFrame(&it, index); if (inlined_jsframe_index == -1) return heap->undefined_value(); // We don't really care what the inlined frame index is, since we are // throwing away the entire frame anyways. diff --git a/deps/v8/src/runtime/runtime-maths.cc b/deps/v8/src/runtime/runtime-maths.cc index 474b463291..504261679e 100644 --- a/deps/v8/src/runtime/runtime-maths.cc +++ b/deps/v8/src/runtime/runtime-maths.cc @@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/assembler.h" #include "src/codegen.h" -#include "src/runtime/runtime-utils.h" #include "src/third_party/fdlibm/fdlibm.h" - namespace v8 { namespace internal { @@ -135,7 +133,7 @@ RUNTIME_FUNCTION(Runtime_MathFloor) { // Slow version of Math.pow. We check for fast paths for special cases. // Used if VFP3 is not available. -RUNTIME_FUNCTION(Runtime_MathPowSlow) { +RUNTIME_FUNCTION(Runtime_MathPow) { HandleScope scope(isolate); DCHECK(args.length() == 2); isolate->counters()->math_pow()->Increment(); @@ -238,12 +236,6 @@ RUNTIME_FUNCTION(Runtime_MathFround) { } -RUNTIME_FUNCTION(Runtime_MathPow) { - SealHandleScope shs(isolate); - return __RT_impl_Runtime_MathPowSlow(args, isolate); -} - - RUNTIME_FUNCTION(Runtime_IsMinusZero) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); diff --git a/deps/v8/src/runtime/runtime-numbers.cc b/deps/v8/src/runtime/runtime-numbers.cc index 3be4cc0f9f..49734ba8dd 100644 --- a/deps/v8/src/runtime/runtime-numbers.cc +++ b/deps/v8/src/runtime/runtime-numbers.cc @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/base/bits.h" #include "src/bootstrapper.h" #include "src/codegen.h" -#include "src/runtime/runtime-utils.h" #ifndef _STLP_VENDOR_CSTD @@ -231,7 +230,7 @@ RUNTIME_FUNCTION(Runtime_StringParseFloat) { } -RUNTIME_FUNCTION(Runtime_NumberToStringRT) { +RUNTIME_FUNCTION(Runtime_NumberToString) { HandleScope scope(isolate); DCHECK(args.length() == 1); CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0); @@ -271,24 +270,6 @@ RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) { } -RUNTIME_FUNCTION(Runtime_NumberToJSUint32) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - - CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]); - return *isolate->factory()->NewNumberFromUint(number); -} - - -RUNTIME_FUNCTION(Runtime_NumberToJSInt32) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - - CONVERT_DOUBLE_ARG_CHECKED(number, 0); - return *isolate->factory()->NewNumberFromInt(DoubleToInt32(number)); -} - - // Converts a Number to a Smi, if possible. Returns NaN if the number is not // a small integer. RUNTIME_FUNCTION(Runtime_NumberToSmi) { @@ -558,12 +539,6 @@ RUNTIME_FUNCTION(Runtime_MaxSmi) { } -RUNTIME_FUNCTION(Runtime_NumberToString) { - SealHandleScope shs(isolate); - return __RT_impl_Runtime_NumberToStringRT(args, isolate); -} - - RUNTIME_FUNCTION(Runtime_IsSmi) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); diff --git a/deps/v8/src/runtime/runtime-object.cc b/deps/v8/src/runtime/runtime-object.cc index 9536ec0cc4..26f74efd15 100644 --- a/deps/v8/src/runtime/runtime-object.cc +++ b/deps/v8/src/runtime/runtime-object.cc @@ -2,42 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/bootstrapper.h" -#include "src/debug.h" +#include "src/debug/debug.h" #include "src/messages.h" #include "src/runtime/runtime.h" -#include "src/runtime/runtime-utils.h" namespace v8 { namespace internal { -// Returns a single character string where first character equals -// string->Get(index). -static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { - DCHECK_LT(index, static_cast<uint32_t>(string->length())); - Factory* factory = string->GetIsolate()->factory(); - return factory->LookupSingleCharacterStringFromCode( - String::Flatten(string)->Get(index)); -} - - -MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate, - Handle<Object> object, - uint32_t index, - LanguageMode language_mode) { - // Handle [] indexing on Strings - if (object->IsString() && - index < static_cast<uint32_t>(String::cast(*object)->length())) { - Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); - if (!result->IsUndefined()) return result; - } - - return Object::GetElement(isolate, object, index, language_mode); -} - MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) { if (key->IsName()) { @@ -65,7 +40,7 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, // Check if the given key is an array index. uint32_t index = 0; if (key->ToArrayIndex(&index)) { - return GetElementOrCharAt(isolate, object, index, language_mode); + return Object::GetElement(isolate, object, index, language_mode); } // Convert the key to a name - possibly by calling back into JavaScript. @@ -77,7 +52,7 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and // remove the special casing here. if (name->AsArrayIndex(&index)) { - return GetElementOrCharAt(isolate, object, index); + return Object::GetElement(isolate, object, index); } else { return Object::GetProperty(object, name, language_mode); } @@ -153,7 +128,9 @@ MaybeHandle<Object> Runtime::KeyedGetObjectProperty( Handle<String> str = Handle<String>::cast(receiver_obj); int index = Handle<Smi>::cast(key_obj)->value(); if (index >= 0 && index < str->length()) { - return GetCharAt(str, index); + Factory* factory = isolate->factory(); + return factory->LookupSingleCharacterStringFromCode( + String::Flatten(str)->Get(index)); } } @@ -194,18 +171,13 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, // Check if the given key is an array index. uint32_t index = 0; if (key->ToArrayIndex(&index)) { - // TODO(verwaest): Support other objects as well. - if (!object->IsJSReceiver()) return value; - return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index, - value, language_mode); + return Object::SetElement(isolate, object, index, value, language_mode); } Handle<Name> name; ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name); - // TODO(verwaest): Support other objects as well. - if (it.IsElement() && !object->IsJSReceiver()) return value; return Object::SetProperty(&it, value, language_mode, Object::MAY_BE_STORE_FROM_KEYED); } @@ -220,10 +192,7 @@ MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && !isolate->MayAccess( Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) { - isolate->ReportFailedAccessCheck( - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); - return isolate->factory()->undefined_value(); + return isolate->factory()->null_value(); } iter.AdvanceIgnoringProxies(); if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { @@ -294,17 +263,12 @@ RUNTIME_FUNCTION(Runtime_SetPrototype) { RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) { - HandleScope shs(isolate); + SealHandleScope shs(isolate); DCHECK(args.length() == 2); // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). - CONVERT_ARG_HANDLE_CHECKED(Object, O, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, V, 1); - PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER); - while (true) { - iter.AdvanceIgnoringProxies(); - if (iter.IsAtEnd()) return isolate->heap()->false_value(); - if (iter.IsAtEnd(O)) return isolate->heap()->true_value(); - } + CONVERT_ARG_CHECKED(Object, O, 0); + CONVERT_ARG_CHECKED(Object, V, 1); + return isolate->heap()->ToBoolean(V->HasInPrototypeChain(isolate, O)); } @@ -448,6 +412,102 @@ RUNTIME_FUNCTION(Runtime_ObjectSeal) { } +RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) { + HandleScope scope(isolate); + DCHECK_EQ(1, args.length()); + CONVERT_SMI_ARG_CHECKED(slot, 0); + + // Go up context chain to the script context. + Handle<Context> script_context(isolate->context()->script_context(), isolate); + DCHECK(script_context->IsScriptContext()); + DCHECK(script_context->get(slot)->IsPropertyCell()); + + // Lookup the named property on the global object. + Handle<ScopeInfo> scope_info(ScopeInfo::cast(script_context->extension()), + isolate); + Handle<Name> name(scope_info->ContextSlotName(slot), isolate); + Handle<GlobalObject> global_object(script_context->global_object(), isolate); + LookupIterator it(global_object, name, LookupIterator::HIDDEN); + + // Switch to fast mode only if there is a data property and it's not on + // a hidden prototype. + if (it.state() == LookupIterator::DATA && + it.GetHolder<Object>().is_identical_to(global_object)) { + // Now update the cell in the script context. + Handle<PropertyCell> cell = it.GetPropertyCell(); + script_context->set(slot, *cell); + } else { + // This is not a fast case, so keep this access in a slow mode. + // Store empty_property_cell here to release the outdated property cell. + script_context->set(slot, isolate->heap()->empty_property_cell()); + } + + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); + return *result; +} + + +namespace { + +Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value, + LanguageMode language_mode) { + // Go up context chain to the script context. + Handle<Context> script_context(isolate->context()->script_context(), isolate); + DCHECK(script_context->IsScriptContext()); + DCHECK(script_context->get(slot)->IsPropertyCell()); + + // Lookup the named property on the global object. + Handle<ScopeInfo> scope_info(ScopeInfo::cast(script_context->extension()), + isolate); + Handle<Name> name(scope_info->ContextSlotName(slot), isolate); + Handle<GlobalObject> global_object(script_context->global_object(), isolate); + LookupIterator it(global_object, name, LookupIterator::HIDDEN); + + // Switch to fast mode only if there is a data property and it's not on + // a hidden prototype. + if (it.state() == LookupIterator::DATA && + it.GetHolder<Object>().is_identical_to(global_object)) { + // Now update cell in the script context. + Handle<PropertyCell> cell = it.GetPropertyCell(); + script_context->set(slot, *cell); + } else { + // This is not a fast case, so keep this access in a slow mode. + // Store empty_property_cell here to release the outdated property cell. + script_context->set(slot, isolate->heap()->empty_property_cell()); + } + + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, + Object::SetProperty(&it, value, language_mode, + Object::CERTAINLY_NOT_STORE_FROM_KEYED)); + return *result; +} + +} // namespace + + +RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_SMI_ARG_CHECKED(slot, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); + + return StoreGlobalViaContext(isolate, slot, value, SLOPPY); +} + + +RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_SMI_ARG_CHECKED(slot, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); + + return StoreGlobalViaContext(isolate, slot, value, STRICT); +} + + RUNTIME_FUNCTION(Runtime_GetProperty) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -605,12 +665,16 @@ RUNTIME_FUNCTION(Runtime_SetProperty) { } -RUNTIME_FUNCTION(Runtime_DeleteProperty) { - HandleScope scope(isolate); - DCHECK(args.length() == 3); - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); - CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2); +namespace { + +// ES6 section 12.5.4. +Object* DeleteProperty(Isolate* isolate, Handle<Object> object, + Handle<Object> key, LanguageMode language_mode) { + Handle<JSReceiver> receiver; + if (!JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); + } Handle<Object> result; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, result, @@ -618,6 +682,26 @@ RUNTIME_FUNCTION(Runtime_DeleteProperty) { return *result; } +} // namespace + + +RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); + return DeleteProperty(isolate, object, key, SLOPPY); +} + + +RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); + return DeleteProperty(isolate, object, key, STRICT); +} + static Object* HasOwnPropertyImplementation(Isolate* isolate, Handle<JSObject> object, @@ -728,26 +812,10 @@ RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) { } -RUNTIME_FUNCTION(Runtime_GetPropertyNames) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); - Handle<JSArray> result; - - isolate->counters()->for_in()->Increment(); - Handle<FixedArray> elements; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, elements, - JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS)); - return *isolate->factory()->NewJSArrayWithElements(elements); -} - - -// Returns either a FixedArray as Runtime_GetPropertyNames, -// or, if the given object has an enum cache that contains -// all enumerable properties of the object and its prototypes -// have none, the map of the object. This is used to speed up -// the check for deletions during a for-in. +// Returns either a FixedArray or, if the given object has an enum cache that +// contains all enumerable properties of the object and its prototypes have +// none, the map of the object. This is used to speed up the check for +// deletions during a for-in. RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); @@ -770,19 +838,6 @@ RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) { } -// Find the length of the prototype chain that is to be handled as one. If a -// prototype object is hidden it is to be viewed as part of the the object it -// is prototype for. -static int OwnPrototypeChainLength(JSObject* obj) { - int count = 1; - for (PrototypeIterator iter(obj->GetIsolate(), obj); - !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { - count++; - } - return count; -} - - // Return the names of the own named properties. // args[0]: object // args[1]: PropertyAttributes as int @@ -792,47 +847,18 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { if (!args[0]->IsJSObject()) { return isolate->heap()->undefined_value(); } - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); CONVERT_SMI_ARG_CHECKED(filter_value, 1); PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value); - // Skip the global proxy as it has no properties and always delegates to the - // real global object. - if (obj->IsJSGlobalProxy()) { - // Only collect names if access is permitted. - if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) { - isolate->ReportFailedAccessCheck(obj); - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); - return *isolate->factory()->NewJSArray(0); - } - PrototypeIterator iter(isolate, obj); - obj = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); - } - - // Find the number of objects making up this. - int length = OwnPrototypeChainLength(*obj); - // Find the number of own properties for each of the objects. - ScopedVector<int> own_property_count(length); int total_property_count = 0; - { - PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); - for (int i = 0; i < length; i++) { - DCHECK(!iter.IsAtEnd()); - Handle<JSObject> jsproto = - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); - // Only collect names if access is permitted. - if (jsproto->IsAccessCheckNeeded() && !isolate->MayAccess(jsproto)) { - isolate->ReportFailedAccessCheck(jsproto); - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); - return *isolate->factory()->NewJSArray(0); - } - int n; - n = jsproto->NumberOfOwnProperties(filter); - own_property_count[i] = n; - total_property_count += n; - iter.Advance(); - } + for (PrototypeIterator iter(isolate, object, + PrototypeIterator::START_AT_RECEIVER); + !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { + Handle<JSObject> jsproto = + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); + total_property_count += jsproto->NumberOfOwnProperties(filter); } // Allocate an array with storage for all the property names. @@ -842,53 +868,69 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { // Get the property names. int next_copy_index = 0; int hidden_strings = 0; - { - PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); - for (int i = 0; i < length; i++) { - DCHECK(!iter.IsAtEnd()); - Handle<JSObject> jsproto = - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); - jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); - // Names from hidden prototypes may already have been added - // for inherited function template instances. Count the duplicates - // and stub them out; the final copy pass at the end ignores holes. - for (int j = next_copy_index; j < next_copy_index + own_property_count[i]; - j++) { - Object* name_from_hidden_proto = names->get(j); - if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) { - hidden_strings++; - } else { - for (int k = 0; k < next_copy_index; k++) { - Object* name = names->get(k); - if (name_from_hidden_proto == name) { - names->set(j, isolate->heap()->hidden_string()); - hidden_strings++; - break; - } + Handle<Object> hidden_string = isolate->factory()->hidden_string(); + for (PrototypeIterator iter(isolate, object, + PrototypeIterator::START_AT_RECEIVER); + !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { + Handle<JSObject> jsproto = + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); + int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); + // Names from hidden prototypes may already have been added + // for inherited function template instances. Count the duplicates + // and stub them out; the final copy pass at the end ignores holes. + for (int j = next_copy_index; j < next_copy_index + own; j++) { + Object* name_from_hidden_proto = names->get(j); + if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) { + hidden_strings++; + } else { + for (int k = 0; k < next_copy_index; k++) { + Object* name = names->get(k); + if (name_from_hidden_proto == name) { + names->set(j, *hidden_string); + hidden_strings++; + break; } } } - next_copy_index += own_property_count[i]; + } + next_copy_index += own; + } + + CHECK_EQ(total_property_count, next_copy_index); - iter.Advance(); + if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { + for (int i = 0; i < total_property_count; i++) { + Handle<Name> name(Name::cast(names->get(i))); + if (name.is_identical_to(hidden_string)) continue; + LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); + if (!JSObject::AllCanRead(&it)) { + names->set(i, *hidden_string); + hidden_strings++; + } } } // Filter out name of hidden properties object and // hidden prototype duplicates. if (hidden_strings > 0) { - Handle<FixedArray> old_names = names; - names = isolate->factory()->NewFixedArray(names->length() - hidden_strings); - int dest_pos = 0; - for (int i = 0; i < total_property_count; i++) { - Object* name = old_names->get(i); - if (isolate->IsInternallyUsedPropertyName(name)) { - hidden_strings--; - continue; + if (hidden_strings == total_property_count) { + names = isolate->factory()->empty_fixed_array(); + } else { + int i; + for (i = 0; i < total_property_count; i++) { + Object* name = names->get(i); + if (name == *hidden_string) break; } - names->set(dest_pos++, name); + int dest_pos = i; + for (; i < total_property_count; i++) { + Object* name = names->get(i); + if (name == *hidden_string) continue; + names->set(dest_pos++, name); + } + + isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( + *names, hidden_strings); } - DCHECK_EQ(0, hidden_strings); } return *isolate->factory()->NewJSArrayWithElements(names); @@ -970,20 +1012,6 @@ RUNTIME_FUNCTION(Runtime_OwnKeys) { CONVERT_ARG_CHECKED(JSObject, raw_object, 0); Handle<JSObject> object(raw_object); - if (object->IsJSGlobalProxy()) { - // Do access checks before going to the global object. - if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { - isolate->ReportFailedAccessCheck(object); - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); - return *isolate->factory()->NewJSArray(0); - } - - PrototypeIterator iter(isolate, object); - // If proxy is detached we simply return an empty array. - if (iter.IsAtEnd()) return *isolate->factory()->NewJSArray(0); - object = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); - } - Handle<FixedArray> contents; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, contents, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY)); @@ -1022,15 +1050,6 @@ RUNTIME_FUNCTION(Runtime_ToFastProperties) { } -RUNTIME_FUNCTION(Runtime_ToBool) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(Object, object, 0); - - return isolate->heap()->ToBoolean(object->BooleanValue()); -} - - RUNTIME_FUNCTION(Runtime_NewStringWrapper) { HandleScope scope(isolate); DCHECK(args.length() == 1); @@ -1192,7 +1211,7 @@ RUNTIME_FUNCTION(Runtime_LoadMutableDouble) { FieldIndex::ForLoadByFieldIndex(object->map(), index->value()); if (field_index.is_inobject()) { RUNTIME_ASSERT(field_index.property_index() < - object->map()->inobject_properties()); + object->map()->GetInObjectProperties()); } else { RUNTIME_ASSERT(field_index.outobject_array_index() < object->properties()->length()); @@ -1371,14 +1390,6 @@ RUNTIME_FUNCTION(Runtime_IsObject) { } -RUNTIME_FUNCTION(Runtime_IsUndetectableObject) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(Object, obj, 0); - return isolate->heap()->ToBoolean(obj->IsUndetectableObject()); -} - - RUNTIME_FUNCTION(Runtime_IsSpecObject) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); @@ -1437,6 +1448,29 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) { } +RUNTIME_FUNCTION(Runtime_ToObject) { + HandleScope scope(isolate); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + Handle<JSReceiver> receiver; + if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) { + return *receiver; + } + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); +} + + +RUNTIME_FUNCTION(Runtime_StrictEquals) { + SealHandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_CHECKED(Object, x, 0); + CONVERT_ARG_CHECKED(Object, y, 1); + // TODO(bmeurer): Change this at some point to return true/false instead. + return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL); +} + + RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) { SealHandleScope shs(isolate); DCHECK_EQ(1, args.length()); diff --git a/deps/v8/src/runtime/runtime-observe.cc b/deps/v8/src/runtime/runtime-observe.cc index 8fc201da0e..e4ce23f87e 100644 --- a/deps/v8/src/runtime/runtime-observe.cc +++ b/deps/v8/src/runtime/runtime-observe.cc @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" -#include "src/debug.h" -#include "src/runtime/runtime-utils.h" +#include "src/debug/debug.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime-proxy.cc b/deps/v8/src/runtime/runtime-proxy.cc index 0f175c0168..03af691cf3 100644 --- a/deps/v8/src/runtime/runtime-proxy.cc +++ b/deps/v8/src/runtime/runtime-proxy.cc @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" -#include "src/runtime/runtime-utils.h" +#include "src/factory.h" +#include "src/objects-inl.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime-regexp.cc b/deps/v8/src/runtime/runtime-regexp.cc index efa91b8485..de671f5783 100644 --- a/deps/v8/src/runtime/runtime-regexp.cc +++ b/deps/v8/src/runtime/runtime-regexp.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" -#include "src/jsregexp-inl.h" -#include "src/jsregexp.h" +#include "src/conversions-inl.h" #include "src/messages.h" +#include "src/regexp/jsregexp-inl.h" +#include "src/regexp/jsregexp.h" #include "src/runtime/runtime-utils.h" #include "src/string-builder.h" #include "src/string-search.h" @@ -643,7 +644,7 @@ MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString( if (!heap->lo_space()->Contains(*answer)) { heap->CreateFillerObjectAt(end_of_string, delta); } - heap->AdjustLiveBytes(answer->address(), -delta, Heap::CONCURRENT_TO_SWEEPER); + heap->AdjustLiveBytes(*answer, -delta, Heap::CONCURRENT_TO_SWEEPER); return *answer; } @@ -784,7 +785,7 @@ RUNTIME_FUNCTION(Runtime_RegExpExec) { } -RUNTIME_FUNCTION(Runtime_RegExpConstructResultRT) { +RUNTIME_FUNCTION(Runtime_RegExpConstructResult) { HandleScope handle_scope(isolate); DCHECK(args.length() == 3); CONVERT_SMI_ARG_CHECKED(size, 0); @@ -794,7 +795,7 @@ RUNTIME_FUNCTION(Runtime_RegExpConstructResultRT) { Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size); Handle<Map> regexp_map(isolate->native_context()->regexp_result_map()); Handle<JSObject> object = - isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED, false); + isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED); Handle<JSArray> array = Handle<JSArray>::cast(object); array->set_elements(*elements); array->set_length(Smi::FromInt(size)); @@ -805,12 +806,6 @@ RUNTIME_FUNCTION(Runtime_RegExpConstructResultRT) { } -RUNTIME_FUNCTION(Runtime_RegExpConstructResult) { - SealHandleScope shs(isolate); - return __RT_impl_Runtime_RegExpConstructResultRT(args, isolate); -} - - static JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) { uint32_t value = JSRegExp::NONE; diff --git a/deps/v8/src/runtime/runtime-scopes.cc b/deps/v8/src/runtime/runtime-scopes.cc index 700925db62..01c828bf40 100644 --- a/deps/v8/src/runtime/runtime-scopes.cc +++ b/deps/v8/src/runtime/runtime-scopes.cc @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/accessors.h" #include "src/arguments.h" #include "src/frames-inl.h" #include "src/messages.h" -#include "src/runtime/runtime-utils.h" #include "src/scopeinfo.h" #include "src/scopes.h" @@ -86,12 +85,12 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global, RUNTIME_FUNCTION(Runtime_DeclareGlobals) { HandleScope scope(isolate); - DCHECK(args.length() == 3); + DCHECK_EQ(2, args.length()); Handle<GlobalObject> global(isolate->global_object()); + Handle<Context> context(isolate->context()); - CONVERT_ARG_HANDLE_CHECKED(Context, context, 0); - CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1); - CONVERT_SMI_ARG_CHECKED(flags, 2); + CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); + CONVERT_SMI_ARG_CHECKED(flags, 1); // Traverse the name/value pairs and set the properties. int length = pairs->length(); @@ -202,20 +201,16 @@ RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) { } -RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) { - HandleScope scope(isolate); - DCHECK(args.length() == 4); +namespace { +Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name, + Handle<Object> initial_value, + PropertyAttributes attr) { // Declarations are always made in a function, eval or script context. In // the case of eval code, the context passed is the context of the caller, // which may be some nested context and not the declaration context. - CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0); - Handle<Context> context(context_arg->declaration_context()); - CONVERT_ARG_HANDLE_CHECKED(String, name, 1); - CONVERT_SMI_ARG_CHECKED(attr_arg, 2); - PropertyAttributes attr = static_cast<PropertyAttributes>(attr_arg); - RUNTIME_ASSERT(attr == READ_ONLY || attr == NONE); - CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3); + Handle<Context> context_arg(isolate->context(), isolate); + Handle<Context> context(context_arg->declaration_context(), isolate); // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals. bool is_var = *initial_value == NULL; @@ -230,6 +225,10 @@ RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) { BindingFlags binding_flags; Handle<Object> holder = context->Lookup(name, flags, &index, &attributes, &binding_flags); + if (holder.is_null()) { + // In case of JSProxy, an exception might have been thrown. + if (isolate->has_pending_exception()) return isolate->heap()->exception(); + } Handle<JSObject> object; Handle<Object> value = @@ -290,6 +289,28 @@ RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) { return isolate->heap()->undefined_value(); } +} // namespace + + +RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(String, name, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1); + + return DeclareLookupSlot(isolate, name, initial_value, NONE); +} + + +RUNTIME_FUNCTION(Runtime_DeclareReadOnlyLookupSlot) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(String, name, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1); + + return DeclareLookupSlot(isolate, name, initial_value, READ_ONLY); +} + RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) { HandleScope scope(isolate); @@ -308,6 +329,10 @@ RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) { BindingFlags binding_flags; Handle<Object> holder = context->Lookup(name, flags, &index, &attributes, &binding_flags); + if (holder.is_null()) { + // In case of JSProxy, an exception might have been thrown. + if (isolate->has_pending_exception()) return isolate->heap()->exception(); + } if (index >= 0) { DCHECK(holder->IsContext()); @@ -371,7 +396,7 @@ static Handle<JSObject> NewSloppyArguments(Isolate* isolate, Object** parameters, int argument_count) { CHECK(!IsSubclassConstructor(callee->shared()->kind())); - DCHECK(callee->is_simple_parameter_list()); + DCHECK(callee->has_simple_parameters()); Handle<JSObject> result = isolate->factory()->NewArgumentsObject(callee, argument_count); @@ -492,7 +517,7 @@ RUNTIME_FUNCTION(Runtime_NewArguments) { Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1)); return (is_strict(callee->shared()->language_mode()) || - !callee->is_simple_parameter_list()) + !callee->has_simple_parameters()) ? *NewStrictArguments(isolate, callee, parameters, argument_count) : *NewSloppyArguments(isolate, callee, parameters, argument_count); } @@ -822,7 +847,6 @@ RUNTIME_FUNCTION(Runtime_DeclareModules) { USE(result); break; } - case INTERNAL: case TEMPORARY: case DYNAMIC: case DYNAMIC_GLOBAL: @@ -855,6 +879,8 @@ RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) { // If the slot was not found the result is true. if (holder.is_null()) { + // In case of JSProxy, an exception might have been thrown. + if (isolate->has_pending_exception()) return isolate->heap()->exception(); return isolate->heap()->true_value(); } @@ -1009,11 +1035,19 @@ RUNTIME_FUNCTION(Runtime_StoreLookupSlot) { BindingFlags binding_flags; Handle<Object> holder = context->Lookup(name, flags, &index, &attributes, &binding_flags); - // In case of JSProxy, an exception might have been thrown. - if (isolate->has_pending_exception()) return isolate->heap()->exception(); + if (holder.is_null()) { + // In case of JSProxy, an exception might have been thrown. + if (isolate->has_pending_exception()) return isolate->heap()->exception(); + } // The property was found in a context slot. if (index >= 0) { + if ((binding_flags == MUTABLE_CHECK_INITIALIZED || + binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) && + Handle<Context>::cast(holder)->is_the_hole(index)) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); + } if ((attributes & READ_ONLY) == 0) { Handle<Context>::cast(holder)->set(index, *value); } else if (is_strict(language_mode)) { @@ -1047,7 +1081,16 @@ RUNTIME_FUNCTION(Runtime_StoreLookupSlot) { } -RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) { +RUNTIME_FUNCTION(Runtime_ArgumentsLength) { + SealHandleScope shs(isolate); + DCHECK(args.length() == 0); + JavaScriptFrameIterator it(isolate); + JavaScriptFrame* frame = it.frame(); + return Smi::FromInt(frame->GetArgumentsLength()); +} + + +RUNTIME_FUNCTION(Runtime_Arguments) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0); @@ -1122,20 +1165,5 @@ RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) { Object::GetProperty(isolate->initial_object_prototype(), key)); return *result; } - - -RUNTIME_FUNCTION(Runtime_ArgumentsLength) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 0); - JavaScriptFrameIterator it(isolate); - JavaScriptFrame* frame = it.frame(); - return Smi::FromInt(frame->GetArgumentsLength()); -} - - -RUNTIME_FUNCTION(Runtime_Arguments) { - SealHandleScope shs(isolate); - return __RT_impl_Runtime_GetArgumentsProperty(args, isolate); -} } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-simd.cc b/deps/v8/src/runtime/runtime-simd.cc new file mode 100644 index 0000000000..ce9512e8da --- /dev/null +++ b/deps/v8/src/runtime/runtime-simd.cc @@ -0,0 +1,821 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/runtime/runtime-utils.h" + +#include "src/arguments.h" +#include "src/base/macros.h" +#include "src/conversions.h" +#include "src/factory.h" +#include "src/objects-inl.h" + +// Implement Single Instruction Multiple Data (SIMD) operations as defined in +// the SIMD.js draft spec: +// http://littledan.github.io/simd.html + +namespace v8 { +namespace internal { + +namespace { + +// Functions to convert Numbers to SIMD component types. + +template <typename T> +static T ConvertNumber(double number); + + +template <> +float ConvertNumber<float>(double number) { + return DoubleToFloat32(number); +} + + +template <> +int32_t ConvertNumber<int32_t>(double number) { + return DoubleToInt32(number); +} + + +template <> +int16_t ConvertNumber<int16_t>(double number) { + return static_cast<int16_t>(DoubleToInt32(number)); +} + + +template <> +int8_t ConvertNumber<int8_t>(double number) { + return static_cast<int8_t>(DoubleToInt32(number)); +} + + +// TODO(bbudge): Make this consistent with SIMD instruction results. +inline float RecipApprox(float a) { return 1.0f / a; } + + +// TODO(bbudge): Make this consistent with SIMD instruction results. +inline float RecipSqrtApprox(float a) { return 1.0f / std::sqrt(a); } + + +// Saturating addition for int16_t and int8_t. +template <typename T> +inline T AddSaturate(T a, T b) { + const T max = std::numeric_limits<T>::max(); + const T min = std::numeric_limits<T>::min(); + int32_t result = a + b; + if (result > max) return max; + if (result < min) return min; + return result; +} + + +// Saturating subtraction for int16_t and int8_t. +template <typename T> +inline T SubSaturate(T a, T b) { + const T max = std::numeric_limits<T>::max(); + const T min = std::numeric_limits<T>::min(); + int32_t result = a - b; + if (result > max) return max; + if (result < min) return min; + return result; +} + + +inline float Min(float a, float b) { + if (a < b) return a; + if (a > b) return b; + if (a == b) return std::signbit(a) ? a : b; + return std::numeric_limits<float>::quiet_NaN(); +} + + +inline float Max(float a, float b) { + if (a > b) return a; + if (a < b) return b; + if (a == b) return std::signbit(b) ? a : b; + return std::numeric_limits<float>::quiet_NaN(); +} + + +inline float MinNumber(float a, float b) { + if (std::isnan(a)) return b; + if (std::isnan(b)) return a; + return Min(a, b); +} + + +inline float MaxNumber(float a, float b) { + if (std::isnan(a)) return b; + if (std::isnan(b)) return a; + return Max(a, b); +} + + +inline bool CanCast(int32_t a) { return true; } + + +inline bool CanCast(float a) { + return a > std::numeric_limits<int32_t>::min() && + a < std::numeric_limits<int32_t>::max(); +} + +} // namespace + +//------------------------------------------------------------------- + +// SIMD helper functions. + +RUNTIME_FUNCTION(Runtime_IsSimdValue) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + return isolate->heap()->ToBoolean(args[0]->IsSimd128Value()); +} + + +RUNTIME_FUNCTION(Runtime_SimdToObject) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(Simd128Value, value, 0); + return *Object::ToObject(isolate, value).ToHandleChecked(); +} + + +RUNTIME_FUNCTION(Runtime_SimdEquals) { + SealHandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_CHECKED(Simd128Value, x, 0); + CONVERT_ARG_CHECKED(Simd128Value, y, 1); + return Smi::FromInt(x->Equals(y) ? EQUAL : NOT_EQUAL); +} + + +RUNTIME_FUNCTION(Runtime_SimdSameValue) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(Simd128Value, a, 0); + bool result = false; + // args[1] is of unknown type. + if (args[1]->IsSimd128Value()) { + Simd128Value* b = Simd128Value::cast(args[1]); + if (a->map() == b->map()) { + if (a->IsFloat32x4()) { + result = Float32x4::cast(*a)->SameValue(Float32x4::cast(b)); + } else { + result = a->BitwiseEquals(b); + } + } + } + return isolate->heap()->ToBoolean(result); +} + + +RUNTIME_FUNCTION(Runtime_SimdSameValueZero) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(Simd128Value, a, 0); + bool result = false; + // args[1] is of unknown type. + if (args[1]->IsSimd128Value()) { + Simd128Value* b = Simd128Value::cast(args[1]); + if (a->map() == b->map()) { + if (a->IsFloat32x4()) { + result = Float32x4::cast(*a)->SameValueZero(Float32x4::cast(b)); + } else { + result = a->BitwiseEquals(b); + } + } + } + return isolate->heap()->ToBoolean(result); +} + + +//------------------------------------------------------------------- + +// Utility macros. + +#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ + CONVERT_INT32_ARG_CHECKED(name, index); \ + RUNTIME_ASSERT(name >= 0 && name < lanes); + +#define SIMD_UNARY_OP(type, lane_type, lane_count, op, result) \ + static const int kLaneCount = lane_count; \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = op(a->get_lane(i)); \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); + +#define SIMD_BINARY_OP(type, lane_type, lane_count, op, result) \ + static const int kLaneCount = lane_count; \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = op(a->get_lane(i), b->get_lane(i)); \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); + +#define SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, op, result) \ + static const int kLaneCount = lane_count; \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ + bool lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = a->get_lane(i) op b->get_lane(i); \ + } \ + Handle<bool_type> result = isolate->factory()->New##bool_type(lanes); + +//------------------------------------------------------------------- + +// Common functions. + +#define GET_NUMERIC_ARG(lane_type, name, index) \ + CONVERT_NUMBER_ARG_HANDLE_CHECKED(a, index); \ + name = ConvertNumber<lane_type>(a->Number()); + +#define GET_BOOLEAN_ARG(lane_type, name, index) \ + name = args[index]->BooleanValue(); + +#define SIMD_ALL_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Int32x4, int32_t, 4, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Bool32x4, bool, 4, ToBoolean, GET_BOOLEAN_ARG) \ + FUNCTION(Int16x8, int16_t, 8, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Bool16x8, bool, 8, ToBoolean, GET_BOOLEAN_ARG) \ + FUNCTION(Int8x16, int8_t, 16, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Bool8x16, bool, 16, ToBoolean, GET_BOOLEAN_ARG) + +#define SIMD_CREATE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_Create##type) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == kLaneCount); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + replace(lane_type, lanes[i], i) \ + } \ + return *isolate->factory()->New##type(lanes); \ + } + +#define SIMD_EXTRACT_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##ExtractLane) { \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lane_count); \ + return *isolate->factory()->extract(a->get_lane(lane)); \ + } + +#define SIMD_REPLACE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 3); \ + CONVERT_ARG_HANDLE_CHECKED(type, simd, 0); \ + CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, kLaneCount); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = simd->get_lane(i); \ + } \ + replace(lane_type, lanes[lane], 2); \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +#define SIMD_CHECK_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##Check) { \ + HandleScope scope(isolate); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + return *a; \ + } + +#define SIMD_SWIZZLE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##Swizzle) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1 + kLaneCount); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + CONVERT_SIMD_LANE_ARG_CHECKED(index, i + 1, kLaneCount); \ + lanes[i] = a->get_lane(index); \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +#define SIMD_SHUFFLE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##Shuffle) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2 + kLaneCount); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + CONVERT_SIMD_LANE_ARG_CHECKED(index, i + 2, kLaneCount * 2); \ + lanes[i] = index < kLaneCount ? a->get_lane(index) \ + : b->get_lane(index - kLaneCount); \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_ALL_TYPES(SIMD_CREATE_FUNCTION) +SIMD_ALL_TYPES(SIMD_EXTRACT_FUNCTION) +SIMD_ALL_TYPES(SIMD_REPLACE_FUNCTION) +SIMD_ALL_TYPES(SIMD_CHECK_FUNCTION) +SIMD_ALL_TYPES(SIMD_SWIZZLE_FUNCTION) +SIMD_ALL_TYPES(SIMD_SHUFFLE_FUNCTION) + +//------------------------------------------------------------------- + +// Float-only functions. + +#define SIMD_ABS_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Abs) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, std::abs, result); \ + return *result; \ + } + +#define SIMD_SQRT_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Sqrt) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, std::sqrt, result); \ + return *result; \ + } + +#define SIMD_RECIP_APPROX_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##RecipApprox) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, RecipApprox, result); \ + return *result; \ + } + +#define SIMD_RECIP_SQRT_APPROX_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##RecipSqrtApprox) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, RecipSqrtApprox, result); \ + return *result; \ + } + +#define BINARY_DIV(a, b) (a) / (b) +#define SIMD_DIV_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Div) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_DIV, result); \ + return *result; \ + } + +#define SIMD_MINNUM_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##MinNum) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, MinNumber, result); \ + return *result; \ + } + +#define SIMD_MAXNUM_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##MaxNum) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, MaxNumber, result); \ + return *result; \ + } + +SIMD_ABS_FUNCTION(Float32x4, float, 4) +SIMD_SQRT_FUNCTION(Float32x4, float, 4) +SIMD_RECIP_APPROX_FUNCTION(Float32x4, float, 4) +SIMD_RECIP_SQRT_APPROX_FUNCTION(Float32x4, float, 4) +SIMD_DIV_FUNCTION(Float32x4, float, 4) +SIMD_MINNUM_FUNCTION(Float32x4, float, 4) +SIMD_MAXNUM_FUNCTION(Float32x4, float, 4) + +//------------------------------------------------------------------- + +// Int-only functions. + +#define SIMD_INT_TYPES(FUNCTION) \ + FUNCTION(Int32x4, int32_t, 32, 4) \ + FUNCTION(Int16x8, int16_t, 16, 8) \ + FUNCTION(Int8x16, int8_t, 8, 16) + +#define CONVERT_SHIFT_ARG_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsNumber()); \ + int32_t signed_shift = 0; \ + RUNTIME_ASSERT(args[index]->ToInt32(&signed_shift)); \ + uint32_t name = bit_cast<uint32_t>(signed_shift); + +#define SIMD_LSL_FUNCTION(type, lane_type, lane_bits, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##ShiftLeftByScalar) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ + lane_type lanes[kLaneCount] = {0}; \ + if (shift < lane_bits) { \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = a->get_lane(i) << shift; \ + } \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +#define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##ShiftRightLogicalByScalar) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ + lane_type lanes[kLaneCount] = {0}; \ + if (shift < lane_bits) { \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = static_cast<lane_type>( \ + bit_cast<u##lane_type>(a->get_lane(i)) >> shift); \ + } \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +#define SIMD_ASR_FUNCTION(type, lane_type, lane_bits, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##ShiftRightArithmeticByScalar) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ + if (shift >= lane_bits) shift = lane_bits - 1; \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + int64_t shifted = static_cast<int64_t>(a->get_lane(i)) >> shift; \ + lanes[i] = static_cast<lane_type>(shifted); \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_INT_TYPES(SIMD_LSL_FUNCTION) +SIMD_INT_TYPES(SIMD_LSR_FUNCTION) +SIMD_INT_TYPES(SIMD_ASR_FUNCTION) + +//------------------------------------------------------------------- + +// Bool-only functions. + +#define SIMD_BOOL_TYPES(FUNCTION) \ + FUNCTION(Bool32x4, 4) \ + FUNCTION(Bool16x8, 8) \ + FUNCTION(Bool8x16, 16) + +#define SIMD_ANY_FUNCTION(type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##AnyTrue) { \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + bool result = false; \ + for (int i = 0; i < lane_count; i++) { \ + if (a->get_lane(i)) { \ + result = true; \ + break; \ + } \ + } \ + return isolate->heap()->ToBoolean(result); \ + } + +#define SIMD_ALL_FUNCTION(type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##AllTrue) { \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + bool result = true; \ + for (int i = 0; i < lane_count; i++) { \ + if (!a->get_lane(i)) { \ + result = false; \ + break; \ + } \ + } \ + return isolate->heap()->ToBoolean(result); \ + } + +SIMD_BOOL_TYPES(SIMD_ANY_FUNCTION) +SIMD_BOOL_TYPES(SIMD_ALL_FUNCTION) + +//------------------------------------------------------------------- + +// Small Int-only functions. + +#define SIMD_SMALL_INT_TYPES(FUNCTION) \ + FUNCTION(Int16x8, int16_t, 8) \ + FUNCTION(Int8x16, int8_t, 16) + +#define SIMD_ADD_SATURATE_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##AddSaturate) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, AddSaturate, result); \ + return *result; \ + } + +#define BINARY_SUB(a, b) (a) - (b) +#define SIMD_SUB_SATURATE_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##SubSaturate) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, SubSaturate, result); \ + return *result; \ + } + +SIMD_SMALL_INT_TYPES(SIMD_ADD_SATURATE_FUNCTION) +SIMD_SMALL_INT_TYPES(SIMD_SUB_SATURATE_FUNCTION) + +//------------------------------------------------------------------- + +// Numeric functions. + +#define SIMD_NUMERIC_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4) \ + FUNCTION(Int32x4, int32_t, 4) \ + FUNCTION(Int16x8, int16_t, 8) \ + FUNCTION(Int8x16, int8_t, 16) + +#define SIMD_NEG_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Neg) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, -, result); \ + return *result; \ + } + +#define BINARY_ADD(a, b) (a) + (b) +#define SIMD_ADD_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Add) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_ADD, result); \ + return *result; \ + } + +#define BINARY_SUB(a, b) (a) - (b) +#define SIMD_SUB_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Sub) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_SUB, result); \ + return *result; \ + } + +#define BINARY_MUL(a, b) (a) * (b) +#define SIMD_MUL_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Mul) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_MUL, result); \ + return *result; \ + } + +#define SIMD_MIN_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Min) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, Min, result); \ + return *result; \ + } + +#define SIMD_MAX_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Max) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, Max, result); \ + return *result; \ + } + +SIMD_NUMERIC_TYPES(SIMD_NEG_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_ADD_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_SUB_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_MUL_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_MIN_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_MAX_FUNCTION) + +//------------------------------------------------------------------- + +// Relational functions. + +#define SIMD_RELATIONAL_TYPES(FUNCTION) \ + FUNCTION(Float32x4, Bool32x4, 4) \ + FUNCTION(Int32x4, Bool32x4, 4) \ + FUNCTION(Int16x8, Bool16x8, 8) \ + FUNCTION(Int8x16, Bool8x16, 16) + +#define SIMD_EQUALITY_TYPES(FUNCTION) \ + SIMD_RELATIONAL_TYPES(FUNCTION) \ + FUNCTION(Bool32x4, Bool32x4, 4) \ + FUNCTION(Bool16x8, Bool16x8, 8) \ + FUNCTION(Bool8x16, Bool8x16, 16) + +#define SIMD_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Equal) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, ==, result); \ + return *result; \ + } + +#define SIMD_NOT_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##NotEqual) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, !=, result); \ + return *result; \ + } + +SIMD_EQUALITY_TYPES(SIMD_EQUAL_FUNCTION) +SIMD_EQUALITY_TYPES(SIMD_NOT_EQUAL_FUNCTION) + +#define SIMD_LESS_THAN_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##LessThan) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, <, result); \ + return *result; \ + } + +#define SIMD_LESS_THAN_OR_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##LessThanOrEqual) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, <=, result); \ + return *result; \ + } + +#define SIMD_GREATER_THAN_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##GreaterThan) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, >, result); \ + return *result; \ + } + +#define SIMD_GREATER_THAN_OR_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##GreaterThanOrEqual) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, >=, result); \ + return *result; \ + } + +SIMD_RELATIONAL_TYPES(SIMD_LESS_THAN_FUNCTION) +SIMD_RELATIONAL_TYPES(SIMD_LESS_THAN_OR_EQUAL_FUNCTION) +SIMD_RELATIONAL_TYPES(SIMD_GREATER_THAN_FUNCTION) +SIMD_RELATIONAL_TYPES(SIMD_GREATER_THAN_OR_EQUAL_FUNCTION) + +//------------------------------------------------------------------- + +// Logical functions. + +#define SIMD_LOGICAL_TYPES(FUNCTION) \ + FUNCTION(Int32x4, int32_t, 4, _INT) \ + FUNCTION(Int16x8, int16_t, 8, _INT) \ + FUNCTION(Int8x16, int8_t, 16, _INT) \ + FUNCTION(Bool32x4, bool, 4, _BOOL) \ + FUNCTION(Bool16x8, bool, 8, _BOOL) \ + FUNCTION(Bool8x16, bool, 16, _BOOL) + +#define BINARY_AND_INT(a, b) (a) & (b) +#define BINARY_AND_BOOL(a, b) (a) && (b) +#define SIMD_AND_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##And) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_AND##op, result); \ + return *result; \ + } + +#define BINARY_OR_INT(a, b) (a) | (b) +#define BINARY_OR_BOOL(a, b) (a) || (b) +#define SIMD_OR_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##Or) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_OR##op, result); \ + return *result; \ + } + +#define BINARY_XOR_INT(a, b) (a) ^ (b) +#define BINARY_XOR_BOOL(a, b) (a) != (b) +#define SIMD_XOR_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##Xor) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_XOR##op, result); \ + return *result; \ + } + +#define UNARY_NOT_INT ~ +#define UNARY_NOT_BOOL ! +#define SIMD_NOT_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##Not) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, UNARY_NOT##op, result); \ + return *result; \ + } + +SIMD_LOGICAL_TYPES(SIMD_AND_FUNCTION) +SIMD_LOGICAL_TYPES(SIMD_OR_FUNCTION) +SIMD_LOGICAL_TYPES(SIMD_XOR_FUNCTION) +SIMD_LOGICAL_TYPES(SIMD_NOT_FUNCTION) + +//------------------------------------------------------------------- + +// Select functions. + +#define SIMD_SELECT_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, Bool32x4, 4) \ + FUNCTION(Int32x4, int32_t, Bool32x4, 4) \ + FUNCTION(Int16x8, int16_t, Bool16x8, 8) \ + FUNCTION(Int8x16, int8_t, Bool8x16, 16) + +#define SIMD_SELECT_FUNCTION(type, lane_type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Select) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 3); \ + CONVERT_ARG_HANDLE_CHECKED(bool_type, mask, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 2); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = mask->get_lane(i) ? a->get_lane(i) : b->get_lane(i); \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_SELECT_TYPES(SIMD_SELECT_FUNCTION) + +//------------------------------------------------------------------- + +// Casting functions. + +#define SIMD_FROM_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4, Int32x4, int32_t) \ + FUNCTION(Int32x4, int32_t, 4, Float32x4, float) + +#define SIMD_FROM_FUNCTION(type, lane_type, lane_count, from_type, from_ctype) \ + RUNTIME_FUNCTION(Runtime_##type##From##from_type) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(from_type, a, 0); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + from_ctype a_value = a->get_lane(i); \ + RUNTIME_ASSERT(CanCast(a_value)); \ + lanes[i] = static_cast<lane_type>(a_value); \ + } \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_FROM_TYPES(SIMD_FROM_FUNCTION) + +#define SIMD_FROM_BITS_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4, Int32x4) \ + FUNCTION(Float32x4, float, 4, Int16x8) \ + FUNCTION(Float32x4, float, 4, Int8x16) \ + FUNCTION(Int32x4, int32_t, 4, Float32x4) \ + FUNCTION(Int32x4, int32_t, 4, Int16x8) \ + FUNCTION(Int32x4, int32_t, 4, Int8x16) \ + FUNCTION(Int16x8, int16_t, 8, Float32x4) \ + FUNCTION(Int16x8, int16_t, 8, Int32x4) \ + FUNCTION(Int16x8, int16_t, 8, Int8x16) \ + FUNCTION(Int8x16, int8_t, 16, Float32x4) \ + FUNCTION(Int8x16, int8_t, 16, Int32x4) \ + FUNCTION(Int8x16, int8_t, 16, Int16x8) + +#define SIMD_FROM_BITS_FUNCTION(type, lane_type, lane_count, from_type) \ + RUNTIME_FUNCTION(Runtime_##type##From##from_type##Bits) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(from_type, a, 0); \ + lane_type lanes[kLaneCount]; \ + a->CopyBits(lanes); \ + Handle<type> result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION) + +//------------------------------------------------------------------- + +// Unsigned extract functions. +// TODO(bbudge): remove when spec changes to include unsigned int types. + +RUNTIME_FUNCTION(Runtime_Int16x8UnsignedExtractLane) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(Int16x8, a, 0); + CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 8); + return *isolate->factory()->NewNumber(bit_cast<uint16_t>(a->get_lane(lane))); +} + + +RUNTIME_FUNCTION(Runtime_Int8x16UnsignedExtractLane) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(Int8x16, a, 0); + CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 16); + return *isolate->factory()->NewNumber(bit_cast<uint8_t>(a->get_lane(lane))); +} +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/runtime/runtime-strings.cc b/deps/v8/src/runtime/runtime-strings.cc index 3b9cfbf969..bb4207f202 100644 --- a/deps/v8/src/runtime/runtime-strings.cc +++ b/deps/v8/src/runtime/runtime-strings.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" -#include "src/jsregexp-inl.h" -#include "src/jsregexp.h" -#include "src/runtime/runtime-utils.h" +#include "src/conversions-inl.h" +#include "src/regexp/jsregexp-inl.h" +#include "src/regexp/jsregexp.h" #include "src/string-builder.h" #include "src/string-search.h" @@ -281,7 +281,7 @@ RUNTIME_FUNCTION(Runtime_StringLocaleCompare) { } -RUNTIME_FUNCTION(Runtime_SubStringRT) { +RUNTIME_FUNCTION(Runtime_SubString) { HandleScope scope(isolate); DCHECK(args.length() == 3); @@ -309,13 +309,7 @@ RUNTIME_FUNCTION(Runtime_SubStringRT) { } -RUNTIME_FUNCTION(Runtime_SubString) { - SealHandleScope shs(isolate); - return __RT_impl_Runtime_SubStringRT(args, isolate); -} - - -RUNTIME_FUNCTION(Runtime_StringAddRT) { +RUNTIME_FUNCTION(Runtime_StringAdd) { HandleScope scope(isolate); DCHECK(args.length() == 2); CONVERT_ARG_HANDLE_CHECKED(String, str1, 0); @@ -328,12 +322,6 @@ RUNTIME_FUNCTION(Runtime_StringAddRT) { } -RUNTIME_FUNCTION(Runtime_StringAdd) { - SealHandleScope shs(isolate); - return __RT_impl_Runtime_StringAddRT(args, isolate); -} - - RUNTIME_FUNCTION(Runtime_InternalizeString) { HandleScope handles(isolate); RUNTIME_ASSERT(args.length() == 1); @@ -428,7 +416,7 @@ RUNTIME_FUNCTION(Runtime_CharFromCode) { } -RUNTIME_FUNCTION(Runtime_StringCompareRT) { +RUNTIME_FUNCTION(Runtime_StringCompare) { HandleScope handle_scope(isolate); DCHECK(args.length() == 2); @@ -497,12 +485,6 @@ RUNTIME_FUNCTION(Runtime_StringCompareRT) { } -RUNTIME_FUNCTION(Runtime_StringCompare) { - SealHandleScope shs(isolate); - return __RT_impl_Runtime_StringCompareRT(args, isolate); -} - - RUNTIME_FUNCTION(Runtime_StringBuilderConcat) { HandleScope scope(isolate); DCHECK(args.length() == 3); diff --git a/deps/v8/src/runtime/runtime-symbol.cc b/deps/v8/src/runtime/runtime-symbol.cc index 412ee0ae31..8f99a37c42 100644 --- a/deps/v8/src/runtime/runtime-symbol.cc +++ b/deps/v8/src/runtime/runtime-symbol.cc @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" -#include "src/runtime/runtime-utils.h" +#include "src/objects-inl.h" namespace v8 { namespace internal { @@ -51,14 +51,6 @@ RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) { } -RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0); - return *Object::ToObject(isolate, symbol).ToHandleChecked(); -} - - RUNTIME_FUNCTION(Runtime_SymbolDescription) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); diff --git a/deps/v8/src/runtime/runtime-test.cc b/deps/v8/src/runtime/runtime-test.cc index 1325eeb67b..73f6478338 100644 --- a/deps/v8/src/runtime/runtime-test.cc +++ b/deps/v8/src/runtime/runtime-test.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/deoptimizer.h" -#include "src/full-codegen.h" -#include "src/runtime/runtime-utils.h" +#include "src/frames-inl.h" +#include "src/full-codegen/full-codegen.h" #include "src/snapshot/natives.h" namespace v8 { @@ -342,7 +342,7 @@ RUNTIME_FUNCTION(Runtime_SetFlags) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); CONVERT_ARG_CHECKED(String, arg, 0); - SmartArrayPointer<char> flags = + base::SmartArrayPointer<char> flags = arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get())); return isolate->heap()->undefined_value(); @@ -378,7 +378,8 @@ RUNTIME_FUNCTION(Runtime_AbortJS) { RUNTIME_FUNCTION(Runtime_NativeScriptsCount) { DCHECK(args.length() == 0); return Smi::FromInt(Natives::GetBuiltinsCount() + - ExtraNatives::GetBuiltinsCount()); + ExtraNatives::GetBuiltinsCount() + + CodeStubNatives::GetBuiltinsCount()); } @@ -479,24 +480,13 @@ ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements) ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements) -ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FixedTypedArrayElements) // Properties test sitting with elements tests - not fooling anyone. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties) #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION -#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \ - RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \ - CONVERT_ARG_CHECKED(JSObject, obj, 0); \ - return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \ - } - -TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) - -#undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION - - #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \ RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \ CONVERT_ARG_CHECKED(JSObject, obj, 0); \ diff --git a/deps/v8/src/runtime/runtime-typedarray.cc b/deps/v8/src/runtime/runtime-typedarray.cc index 4d35524703..ffa4120903 100644 --- a/deps/v8/src/runtime/runtime-typedarray.cc +++ b/deps/v8/src/runtime/runtime-typedarray.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" +#include "src/factory.h" #include "src/messages.h" +#include "src/objects-inl.h" #include "src/runtime/runtime.h" -#include "src/runtime/runtime-utils.h" - namespace v8 { namespace internal { @@ -159,14 +159,12 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) { void Runtime::ArrayIdToTypeAndSize(int arrayId, ExternalArrayType* array_type, - ElementsKind* external_elements_kind, ElementsKind* fixed_elements_kind, size_t* element_size) { switch (arrayId) { #define ARRAY_ID_CASE(Type, type, TYPE, ctype, size) \ case ARRAY_ID_##TYPE: \ *array_type = kExternal##Type##Array; \ - *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS; \ *fixed_elements_kind = TYPE##_ELEMENTS; \ *element_size = size; \ break; @@ -195,11 +193,9 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. size_t element_size = 1; // Bogus initialization. - ElementsKind external_elements_kind = - EXTERNAL_INT8_ELEMENTS; // Bogus initialization. ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization. - Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind, - &fixed_elements_kind, &element_size); + Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind, + &element_size); RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind); size_t byte_offset = 0; @@ -241,13 +237,11 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); holder->set_buffer(*buffer); - Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( - static_cast<int>(length), array_type, - static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); - Handle<Map> map = - JSObject::GetElementsTransitionMap(holder, external_elements_kind); - JSObject::SetMapAndElements(holder, map, elements); - DCHECK(IsExternalArrayElementsKind(holder->map()->elements_kind())); + Handle<FixedTypedArrayBase> elements = + isolate->factory()->NewFixedTypedArrayWithExternalPointer( + static_cast<int>(length), array_type, + static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); + holder->set_elements(*elements); } else { Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); Runtime::SetupArrayBuffer(isolate, buffer, true, NULL, byte_length, @@ -280,11 +274,9 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) { ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. size_t element_size = 1; // Bogus initialization. - ElementsKind external_elements_kind = - EXTERNAL_INT8_ELEMENTS; // Bogus intialization. ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization. - Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind, - &fixed_elements_kind, &element_size); + Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind, + &element_size); RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind); @@ -340,12 +332,11 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) { holder->set_byte_length(*byte_length_obj); holder->set_length(*length_obj); - Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( - static_cast<int>(length), array_type, - static_cast<uint8_t*>(buffer->backing_store())); - Handle<Map> map = - JSObject::GetElementsTransitionMap(holder, external_elements_kind); - JSObject::SetMapAndElements(holder, map, elements); + Handle<FixedTypedArrayBase> elements = + isolate->factory()->NewFixedTypedArrayWithExternalPointer( + static_cast<int>(length), array_type, + static_cast<uint8_t*>(buffer->backing_store())); + holder->set_elements(*elements); if (source->IsJSTypedArray()) { Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source)); diff --git a/deps/v8/src/runtime/runtime-uri.cc b/deps/v8/src/runtime/runtime-uri.cc index e0eba4fe4b..4f77af81cb 100644 --- a/deps/v8/src/runtime/runtime-uri.cc +++ b/deps/v8/src/runtime/runtime-uri.cc @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/runtime/runtime-utils.h" #include "src/arguments.h" #include "src/conversions.h" -#include "src/runtime/runtime-utils.h" +#include "src/objects-inl.h" #include "src/string-search.h" #include "src/utils.h" - namespace v8 { namespace internal { diff --git a/deps/v8/src/runtime/runtime.cc b/deps/v8/src/runtime/runtime.cc index 674f1173a7..a490327af5 100644 --- a/deps/v8/src/runtime/runtime.cc +++ b/deps/v8/src/runtime/runtime.cc @@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" - #include "src/runtime/runtime.h" + +#include "src/handles-inl.h" +#include "src/heap/heap.h" +#include "src/isolate.h" #include "src/runtime/runtime-utils.h" namespace v8 { diff --git a/deps/v8/src/runtime/runtime.h b/deps/v8/src/runtime/runtime.h index c4f74e7de1..4545426e83 100644 --- a/deps/v8/src/runtime/runtime.h +++ b/deps/v8/src/runtime/runtime.h @@ -66,6 +66,13 @@ namespace internal { F(AtomicsIsLockFree, 1, 1) +#define FOR_EACH_INTRINSIC_FUTEX(F) \ + F(AtomicsFutexWait, 4, 1) \ + F(AtomicsFutexWake, 3, 1) \ + F(AtomicsFutexWakeOrRequeue, 5, 1) \ + F(AtomicsFutexNumWaitersForTesting, 2, 1) + + #define FOR_EACH_INTRINSIC_CLASSES(F) \ F(ThrowNonMethodError, 0, 1) \ F(ThrowUnsupportedSuperError, 0, 1) \ @@ -75,7 +82,9 @@ namespace internal { F(ThrowIfStaticPrototype, 1, 1) \ F(ToMethod, 2, 1) \ F(HomeObjectSymbol, 0, 1) \ - F(DefineClass, 6, 1) \ + F(DefineClass, 5, 1) \ + F(DefineClassStrong, 5, 1) \ + F(FinalizeClassDefinition, 2, 1) \ F(DefineClassMethod, 3, 1) \ F(ClassGetSourceCode, 1, 1) \ F(LoadFromSuper, 4, 1) \ @@ -85,8 +94,7 @@ namespace internal { F(StoreKeyedToSuper_Strict, 4, 1) \ F(StoreKeyedToSuper_Sloppy, 4, 1) \ F(HandleStepInForDerivedConstructors, 1, 1) \ - F(DefaultConstructorCallSuper, 2, 1) \ - F(CallSuperWithSpread, 1, 1) + F(DefaultConstructorCallSuper, 2, 1) #define FOR_EACH_INTRINSIC_COLLECTIONS(F) \ @@ -145,6 +153,7 @@ namespace internal { #define FOR_EACH_INTRINSIC_DEBUG(F) \ + F(HandleDebuggerStatement, 0, 1) \ F(DebugBreak, 0, 1) \ F(SetDebugEventListener, 2, 1) \ F(ScheduleBreak, 0, 1) \ @@ -292,6 +301,9 @@ namespace internal { #define FOR_EACH_INTRINSIC_INTERNAL(F) \ F(CheckIsBootstrapping, 0, 1) \ + F(ImportToRuntime, 1, 1) \ + F(ImportExperimentalToRuntime, 1, 1) \ + F(InstallJSBuiltins, 1, 1) \ F(Throw, 1, 1) \ F(ReThrow, 1, 1) \ F(UnwindAndFindExceptionHandler, 0, 1) \ @@ -311,9 +323,9 @@ namespace internal { F(AllocateInTargetSpace, 2, 1) \ F(CollectStackTrace, 2, 1) \ F(RenderCallSite, 0, 1) \ - F(GetFromCacheRT, 2, 1) \ F(MessageGetStartPosition, 1, 1) \ F(MessageGetScript, 1, 1) \ + F(ErrorToStringRT, 1, 1) \ F(FormatMessageString, 4, 1) \ F(CallSiteGetFileNameRT, 3, 1) \ F(CallSiteGetFunctionNameRT, 3, 1) \ @@ -326,13 +338,13 @@ namespace internal { F(CallSiteIsEvalRT, 3, 1) \ F(CallSiteIsConstructorRT, 3, 1) \ F(IS_VAR, 1, 1) \ - F(GetFromCache, 2, 1) \ F(IncrementStatsCounter, 1, 1) \ F(Likely, 1, 1) \ F(Unlikely, 1, 1) \ F(HarmonyToString, 0, 1) \ F(GetTypeFeedbackVector, 1, 1) \ - F(GetCallerJSFunction, 0, 1) + F(GetCallerJSFunction, 0, 1) \ + F(GetCodeStubExportsObject, 0, 1) #define FOR_EACH_INTRINSIC_JSON(F) \ @@ -375,12 +387,11 @@ namespace internal { F(MathExpRT, 1, 1) \ F(MathClz32, 1, 1) \ F(MathFloor, 1, 1) \ - F(MathPowSlow, 2, 1) \ + F(MathPow, 2, 1) \ F(MathPowRT, 2, 1) \ F(RoundNumber, 1, 1) \ F(MathSqrt, 1, 1) \ F(MathFround, 1, 1) \ - F(MathPow, 2, 1) \ F(IsMinusZero, 1, 1) @@ -393,12 +404,10 @@ namespace internal { F(StringToNumber, 1, 1) \ F(StringParseInt, 2, 1) \ F(StringParseFloat, 1, 1) \ - F(NumberToStringRT, 1, 1) \ + F(NumberToString, 1, 1) \ F(NumberToStringSkipCache, 1, 1) \ F(NumberToInteger, 1, 1) \ F(NumberToIntegerMapMinusZero, 1, 1) \ - F(NumberToJSUint32, 1, 1) \ - F(NumberToJSInt32, 1, 1) \ F(NumberToSmi, 1, 1) \ F(NumberAdd, 2, 1) \ F(NumberSub, 2, 1) \ @@ -417,7 +426,6 @@ namespace internal { F(NumberCompare, 3, 1) \ F(SmiLexicographicCompare, 2, 1) \ F(MaxSmi, 0, 1) \ - F(NumberToString, 1, 1) \ F(IsSmi, 1, 1) \ F(IsNonNegativeSmi, 1, 1) \ F(GetRootNaN, 0, 1) @@ -438,16 +446,19 @@ namespace internal { F(GetPropertyStrong, 2, 1) \ F(KeyedGetProperty, 2, 1) \ F(KeyedGetPropertyStrong, 2, 1) \ + F(LoadGlobalViaContext, 1, 1) \ + F(StoreGlobalViaContext_Sloppy, 2, 1) \ + F(StoreGlobalViaContext_Strict, 2, 1) \ F(AddNamedProperty, 4, 1) \ F(SetProperty, 4, 1) \ F(AddElement, 3, 1) \ F(AppendElement, 2, 1) \ - F(DeleteProperty, 3, 1) \ + F(DeleteProperty_Sloppy, 2, 1) \ + F(DeleteProperty_Strict, 2, 1) \ F(HasOwnProperty, 2, 1) \ F(HasProperty, 2, 1) \ F(HasElement, 2, 1) \ F(IsPropertyEnumerable, 2, 1) \ - F(GetPropertyNames, 1, 1) \ F(GetPropertyNamesFast, 1, 1) \ F(GetOwnPropertyNames, 2, 1) \ F(GetOwnElementNames, 1, 1) \ @@ -456,7 +467,6 @@ namespace internal { F(GetIndexedInterceptorElementNames, 1, 1) \ F(OwnKeys, 1, 1) \ F(ToFastProperties, 1, 1) \ - F(ToBool, 1, 1) \ F(NewStringWrapper, 1, 1) \ F(AllocateHeapNumber, 0, 1) \ F(NewObject, 2, 1) \ @@ -478,12 +488,13 @@ namespace internal { F(MapGetInstanceType, 1, 1) \ F(ObjectEquals, 2, 1) \ F(IsObject, 1, 1) \ - F(IsUndetectableObject, 1, 1) \ F(IsSpecObject, 1, 1) \ F(IsStrong, 1, 1) \ F(ClassOf, 1, 1) \ F(DefineGetterPropertyUnchecked, 4, 1) \ F(DefineSetterPropertyUnchecked, 4, 1) \ + F(ToObject, 1, 1) \ + F(StrictEquals, 2, 1) \ F(IsAccessCheckNeeded, 1, 1) @@ -516,7 +527,6 @@ namespace internal { F(StringReplaceGlobalRegExpWithString, 4, 1) \ F(StringSplit, 3, 1) \ F(RegExpExec, 4, 1) \ - F(RegExpConstructResultRT, 3, 1) \ F(RegExpConstructResult, 3, 1) \ F(RegExpInitializeAndCompile, 3, 1) \ F(MaterializeRegExpLiteral, 4, 1) \ @@ -527,10 +537,11 @@ namespace internal { #define FOR_EACH_INTRINSIC_SCOPES(F) \ F(ThrowConstAssignError, 0, 1) \ - F(DeclareGlobals, 3, 1) \ + F(DeclareGlobals, 2, 1) \ F(InitializeVarGlobal, 3, 1) \ F(InitializeConstGlobal, 2, 1) \ - F(DeclareLookupSlot, 4, 1) \ + F(DeclareLookupSlot, 2, 1) \ + F(DeclareReadOnlyLookupSlot, 2, 1) \ F(InitializeLegacyConstLookupSlot, 3, 1) \ F(NewArguments, 1, 1) /* TODO(turbofan): Only temporary */ \ F(NewSloppyArguments, 3, 1) \ @@ -549,25 +560,195 @@ namespace internal { F(DeclareModules, 1, 1) \ F(DeleteLookupSlot, 2, 1) \ F(StoreLookupSlot, 4, 1) \ - F(GetArgumentsProperty, 1, 1) \ F(ArgumentsLength, 0, 1) \ F(Arguments, 1, 1) +#define FOR_EACH_INTRINSIC_SIMD(F) \ + F(IsSimdValue, 1, 1) \ + F(SimdToObject, 1, 1) \ + F(SimdEquals, 2, 1) \ + F(SimdSameValue, 2, 1) \ + F(SimdSameValueZero, 2, 1) \ + F(CreateFloat32x4, 4, 1) \ + F(CreateInt32x4, 4, 1) \ + F(CreateBool32x4, 4, 1) \ + F(CreateInt16x8, 8, 1) \ + F(CreateBool16x8, 8, 1) \ + F(CreateInt8x16, 16, 1) \ + F(CreateBool8x16, 16, 1) \ + F(Float32x4Check, 1, 1) \ + F(Float32x4ExtractLane, 2, 1) \ + F(Float32x4ReplaceLane, 3, 1) \ + F(Float32x4Abs, 1, 1) \ + F(Float32x4Neg, 1, 1) \ + F(Float32x4Sqrt, 1, 1) \ + F(Float32x4RecipApprox, 1, 1) \ + F(Float32x4RecipSqrtApprox, 1, 1) \ + F(Float32x4Add, 2, 1) \ + F(Float32x4Sub, 2, 1) \ + F(Float32x4Mul, 2, 1) \ + F(Float32x4Div, 2, 1) \ + F(Float32x4Min, 2, 1) \ + F(Float32x4Max, 2, 1) \ + F(Float32x4MinNum, 2, 1) \ + F(Float32x4MaxNum, 2, 1) \ + F(Float32x4LessThan, 2, 1) \ + F(Float32x4LessThanOrEqual, 2, 1) \ + F(Float32x4GreaterThan, 2, 1) \ + F(Float32x4GreaterThanOrEqual, 2, 1) \ + F(Float32x4Equal, 2, 1) \ + F(Float32x4NotEqual, 2, 1) \ + F(Float32x4Select, 3, 1) \ + F(Float32x4Swizzle, 5, 1) \ + F(Float32x4Shuffle, 6, 1) \ + F(Float32x4FromInt32x4, 1, 1) \ + F(Float32x4FromInt32x4Bits, 1, 1) \ + F(Float32x4FromInt16x8Bits, 1, 1) \ + F(Float32x4FromInt8x16Bits, 1, 1) \ + F(Int32x4Check, 1, 1) \ + F(Int32x4ExtractLane, 2, 1) \ + F(Int32x4ReplaceLane, 3, 1) \ + F(Int32x4Neg, 1, 1) \ + F(Int32x4Add, 2, 1) \ + F(Int32x4Sub, 2, 1) \ + F(Int32x4Mul, 2, 1) \ + F(Int32x4Min, 2, 1) \ + F(Int32x4Max, 2, 1) \ + F(Int32x4And, 2, 1) \ + F(Int32x4Or, 2, 1) \ + F(Int32x4Xor, 2, 1) \ + F(Int32x4Not, 1, 1) \ + F(Int32x4ShiftLeftByScalar, 2, 1) \ + F(Int32x4ShiftRightLogicalByScalar, 2, 1) \ + F(Int32x4ShiftRightArithmeticByScalar, 2, 1) \ + F(Int32x4LessThan, 2, 1) \ + F(Int32x4LessThanOrEqual, 2, 1) \ + F(Int32x4GreaterThan, 2, 1) \ + F(Int32x4GreaterThanOrEqual, 2, 1) \ + F(Int32x4Equal, 2, 1) \ + F(Int32x4NotEqual, 2, 1) \ + F(Int32x4Select, 3, 1) \ + F(Int32x4Swizzle, 5, 1) \ + F(Int32x4Shuffle, 6, 1) \ + F(Int32x4FromFloat32x4, 1, 1) \ + F(Int32x4FromFloat32x4Bits, 1, 1) \ + F(Int32x4FromInt16x8Bits, 1, 1) \ + F(Int32x4FromInt8x16Bits, 1, 1) \ + F(Bool32x4Check, 1, 1) \ + F(Bool32x4ExtractLane, 2, 1) \ + F(Bool32x4ReplaceLane, 3, 1) \ + F(Bool32x4And, 2, 1) \ + F(Bool32x4Or, 2, 1) \ + F(Bool32x4Xor, 2, 1) \ + F(Bool32x4Not, 1, 1) \ + F(Bool32x4AnyTrue, 1, 1) \ + F(Bool32x4AllTrue, 1, 1) \ + F(Bool32x4Equal, 2, 1) \ + F(Bool32x4NotEqual, 2, 1) \ + F(Bool32x4Swizzle, 5, 1) \ + F(Bool32x4Shuffle, 6, 1) \ + F(Int16x8Check, 1, 1) \ + F(Int16x8ExtractLane, 2, 1) \ + F(Int16x8UnsignedExtractLane, 2, 1) \ + F(Int16x8ReplaceLane, 3, 1) \ + F(Int16x8Neg, 1, 1) \ + F(Int16x8Add, 2, 1) \ + F(Int16x8AddSaturate, 2, 1) \ + F(Int16x8Sub, 2, 1) \ + F(Int16x8SubSaturate, 2, 1) \ + F(Int16x8Mul, 2, 1) \ + F(Int16x8Min, 2, 1) \ + F(Int16x8Max, 2, 1) \ + F(Int16x8And, 2, 1) \ + F(Int16x8Or, 2, 1) \ + F(Int16x8Xor, 2, 1) \ + F(Int16x8Not, 1, 1) \ + F(Int16x8ShiftLeftByScalar, 2, 1) \ + F(Int16x8ShiftRightLogicalByScalar, 2, 1) \ + F(Int16x8ShiftRightArithmeticByScalar, 2, 1) \ + F(Int16x8LessThan, 2, 1) \ + F(Int16x8LessThanOrEqual, 2, 1) \ + F(Int16x8GreaterThan, 2, 1) \ + F(Int16x8GreaterThanOrEqual, 2, 1) \ + F(Int16x8Equal, 2, 1) \ + F(Int16x8NotEqual, 2, 1) \ + F(Int16x8Select, 3, 1) \ + F(Int16x8Swizzle, 9, 1) \ + F(Int16x8Shuffle, 10, 1) \ + F(Int16x8FromFloat32x4Bits, 1, 1) \ + F(Int16x8FromInt32x4Bits, 1, 1) \ + F(Int16x8FromInt8x16Bits, 1, 1) \ + F(Bool16x8Check, 1, 1) \ + F(Bool16x8ExtractLane, 2, 1) \ + F(Bool16x8ReplaceLane, 3, 1) \ + F(Bool16x8And, 2, 1) \ + F(Bool16x8Or, 2, 1) \ + F(Bool16x8Xor, 2, 1) \ + F(Bool16x8Not, 1, 1) \ + F(Bool16x8AnyTrue, 1, 1) \ + F(Bool16x8AllTrue, 1, 1) \ + F(Bool16x8Equal, 2, 1) \ + F(Bool16x8NotEqual, 2, 1) \ + F(Bool16x8Swizzle, 9, 1) \ + F(Bool16x8Shuffle, 10, 1) \ + F(Int8x16Check, 1, 1) \ + F(Int8x16ExtractLane, 2, 1) \ + F(Int8x16UnsignedExtractLane, 2, 1) \ + F(Int8x16ReplaceLane, 3, 1) \ + F(Int8x16Neg, 1, 1) \ + F(Int8x16Add, 2, 1) \ + F(Int8x16AddSaturate, 2, 1) \ + F(Int8x16Sub, 2, 1) \ + F(Int8x16SubSaturate, 2, 1) \ + F(Int8x16Mul, 2, 1) \ + F(Int8x16Min, 2, 1) \ + F(Int8x16Max, 2, 1) \ + F(Int8x16And, 2, 1) \ + F(Int8x16Or, 2, 1) \ + F(Int8x16Xor, 2, 1) \ + F(Int8x16Not, 1, 1) \ + F(Int8x16ShiftLeftByScalar, 2, 1) \ + F(Int8x16ShiftRightLogicalByScalar, 2, 1) \ + F(Int8x16ShiftRightArithmeticByScalar, 2, 1) \ + F(Int8x16LessThan, 2, 1) \ + F(Int8x16LessThanOrEqual, 2, 1) \ + F(Int8x16GreaterThan, 2, 1) \ + F(Int8x16GreaterThanOrEqual, 2, 1) \ + F(Int8x16Equal, 2, 1) \ + F(Int8x16NotEqual, 2, 1) \ + F(Int8x16Select, 3, 1) \ + F(Int8x16Swizzle, 17, 1) \ + F(Int8x16Shuffle, 18, 1) \ + F(Int8x16FromFloat32x4Bits, 1, 1) \ + F(Int8x16FromInt32x4Bits, 1, 1) \ + F(Int8x16FromInt16x8Bits, 1, 1) \ + F(Bool8x16Check, 1, 1) \ + F(Bool8x16ExtractLane, 2, 1) \ + F(Bool8x16ReplaceLane, 3, 1) \ + F(Bool8x16And, 2, 1) \ + F(Bool8x16Or, 2, 1) \ + F(Bool8x16Xor, 2, 1) \ + F(Bool8x16Not, 1, 1) \ + F(Bool8x16AnyTrue, 1, 1) \ + F(Bool8x16AllTrue, 1, 1) \ + F(Bool8x16Equal, 2, 1) \ + F(Bool8x16NotEqual, 2, 1) \ + F(Bool8x16Swizzle, 17, 1) \ + F(Bool8x16Shuffle, 18, 1) + + #define FOR_EACH_INTRINSIC_STRINGS(F) \ F(StringReplaceOneCharWithString, 3, 1) \ F(StringIndexOf, 3, 1) \ F(StringLastIndexOf, 3, 1) \ F(StringLocaleCompare, 2, 1) \ - F(SubStringRT, 3, 1) \ F(SubString, 3, 1) \ - F(StringAddRT, 2, 1) \ F(StringAdd, 2, 1) \ F(InternalizeString, 1, 1) \ F(StringMatch, 3, 1) \ F(StringCharCodeAtRT, 2, 1) \ F(CharFromCode, 1, 1) \ - F(StringCompareRT, 2, 1) \ F(StringCompare, 2, 1) \ F(StringBuilderConcat, 3, 1) \ F(StringBuilderJoin, 3, 1) \ @@ -596,7 +777,6 @@ namespace internal { F(CreateSymbol, 1, 1) \ F(CreatePrivateSymbol, 1, 1) \ F(CreateGlobalPrivateSymbol, 1, 1) \ - F(NewSymbolWrapper, 1, 1) \ F(SymbolDescription, 1, 1) \ F(SymbolRegistry, 0, 1) \ F(SymbolIsPrivate, 1, 1) @@ -637,17 +817,8 @@ namespace internal { F(HasFastHoleyElements, 1, 1) \ F(HasDictionaryElements, 1, 1) \ F(HasSloppyArgumentsElements, 1, 1) \ - F(HasExternalArrayElements, 1, 1) \ + F(HasFixedTypedArrayElements, 1, 1) \ F(HasFastProperties, 1, 1) \ - F(HasExternalUint8Elements, 1, 1) \ - F(HasExternalInt8Elements, 1, 1) \ - F(HasExternalUint16Elements, 1, 1) \ - F(HasExternalInt16Elements, 1, 1) \ - F(HasExternalUint32Elements, 1, 1) \ - F(HasExternalInt32Elements, 1, 1) \ - F(HasExternalFloat32Elements, 1, 1) \ - F(HasExternalFloat64Elements, 1, 1) \ - F(HasExternalUint8ClampedElements, 1, 1) \ F(HasFixedUint8Elements, 1, 1) \ F(HasFixedInt8Elements, 1, 1) \ F(HasFixedUint16Elements, 1, 1) \ @@ -706,7 +877,37 @@ namespace internal { F(LoadLookupSlotNoReferenceError, 2, 2) +// Most intrinsics are implemented in the runtime/ directory, but ICs are +// implemented in ic.cc for now. +#define FOR_EACH_INTRINSIC_IC(F) \ + F(LoadIC_Miss, 3, 1) \ + F(KeyedLoadIC_Miss, 3, 1) \ + F(CallIC_Miss, 3, 1) \ + F(CallIC_Customization_Miss, 3, 1) \ + F(StoreIC_Miss, 3, 1) \ + F(StoreIC_Slow, 3, 1) \ + F(KeyedStoreIC_Miss, 3, 1) \ + F(KeyedStoreIC_Slow, 3, 1) \ + F(StoreCallbackProperty, 5, 1) \ + F(LoadPropertyWithInterceptorOnly, 3, 1) \ + F(LoadPropertyWithInterceptor, 3, 1) \ + F(LoadElementWithInterceptor, 2, 1) \ + F(StorePropertyWithInterceptor, 3, 1) \ + F(CompareIC_Miss, 3, 1) \ + F(BinaryOpIC_Miss, 2, 1) \ + F(CompareNilIC_Miss, 1, 1) \ + F(Unreachable, 0, 1) \ + F(ToBooleanIC_Miss, 1, 1) \ + F(KeyedLoadIC_MissFromStubFailure, 4, 1) \ + F(KeyedStoreIC_MissFromStubFailure, 3, 1) \ + F(StoreIC_MissFromStubFailure, 3, 1) \ + F(ElementsTransitionAndStoreIC_Miss, 4, 1) \ + F(BinaryOpIC_MissWithAllocationSite, 3, 1) \ + F(LoadIC_MissFromStubFailure, 0, 1) + + #define FOR_EACH_INTRINSIC_RETURN_OBJECT(F) \ + FOR_EACH_INTRINSIC_IC(F) \ FOR_EACH_INTRINSIC_ARRAY(F) \ FOR_EACH_INTRINSIC_ATOMICS(F) \ FOR_EACH_INTRINSIC_CLASSES(F) \ @@ -716,6 +917,7 @@ namespace internal { FOR_EACH_INTRINSIC_DEBUG(F) \ FOR_EACH_INTRINSIC_FORIN(F) \ FOR_EACH_INTRINSIC_FUNCTION(F) \ + FOR_EACH_INTRINSIC_FUTEX(F) \ FOR_EACH_INTRINSIC_GENERATOR(F) \ FOR_EACH_INTRINSIC_I18N(F) \ FOR_EACH_INTRINSIC_INTERNAL(F) \ @@ -729,6 +931,7 @@ namespace internal { FOR_EACH_INTRINSIC_PROXY(F) \ FOR_EACH_INTRINSIC_REGEXP(F) \ FOR_EACH_INTRINSIC_SCOPES(F) \ + FOR_EACH_INTRINSIC_SIMD(F) \ FOR_EACH_INTRINSIC_STRINGS(F) \ FOR_EACH_INTRINSIC_SYMBOL(F) \ FOR_EACH_INTRINSIC_TEST(F) \ @@ -742,6 +945,12 @@ namespace internal { FOR_EACH_INTRINSIC_RETURN_OBJECT(F) +#define F(name, nargs, ressize) \ + Object* Runtime_##name(int args_length, Object** args_object, \ + Isolate* isolate); +FOR_EACH_INTRINSIC_RETURN_OBJECT(F) +#undef F + //--------------------------------------------------------------------------- // Runtime provides access to all C++ runtime functions. @@ -815,15 +1024,6 @@ class Runtime : public AllStatic { // Get the intrinsic function with the given function entry address. static const Function* FunctionForEntry(Address ref); - // TODO(1240886): Some of the following methods are *not* handle safe, but - // accept handle arguments. This seems fragile. - - // Support getting the characters in a string using [] notation as - // in Firefox/SpiderMonkey, Safari and Opera. - MUST_USE_RESULT static MaybeHandle<Object> GetElementOrCharAt( - Isolate* isolate, Handle<Object> object, uint32_t index, - LanguageMode language_mode = SLOPPY); - MUST_USE_RESULT static MaybeHandle<Object> DeleteObjectProperty( Isolate* isolate, Handle<JSReceiver> receiver, Handle<Object> key, LanguageMode language_mode); @@ -859,8 +1059,6 @@ class Runtime : public AllStatic { static void NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer); - static int FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index); - enum TypedArrayId { // arrayIds below should be synchromized with typedarray.js natives. ARRAY_ID_UINT8 = 1, @@ -877,7 +1075,6 @@ class Runtime : public AllStatic { }; static void ArrayIdToTypeAndSize(int array_id, ExternalArrayType* type, - ElementsKind* external_elements_kind, ElementsKind* fixed_elements_kind, size_t* element_size); |