summaryrefslogtreecommitdiff
path: root/chromium/v8/src/runtime
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-12 14:07:37 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-17 10:29:26 +0000
commitec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch)
tree25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/v8/src/runtime
parentbb09965444b5bb20b096a291445170876225268d (diff)
downloadqtwebengine-chromium-ec02ee4181c49b61fce1c8fb99292dbb8139cc90.tar.gz
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/v8/src/runtime')
-rw-r--r--chromium/v8/src/runtime/runtime-array.cc14
-rw-r--r--chromium/v8/src/runtime/runtime-atomics.cc216
-rw-r--r--chromium/v8/src/runtime/runtime-classes.cc7
-rw-r--r--chromium/v8/src/runtime/runtime-compiler.cc27
-rw-r--r--chromium/v8/src/runtime/runtime-debug.cc16
-rw-r--r--chromium/v8/src/runtime/runtime-forin.cc2
-rw-r--r--chromium/v8/src/runtime/runtime-futex.cc38
-rw-r--r--chromium/v8/src/runtime/runtime-generator.cc30
-rw-r--r--chromium/v8/src/runtime/runtime-i18n.cc412
-rw-r--r--chromium/v8/src/runtime/runtime-internal.cc71
-rw-r--r--chromium/v8/src/runtime/runtime-liveedit.cc2
-rw-r--r--chromium/v8/src/runtime/runtime-maths.cc16
-rw-r--r--chromium/v8/src/runtime/runtime-module.cc33
-rw-r--r--chromium/v8/src/runtime/runtime-numbers.cc7
-rw-r--r--chromium/v8/src/runtime/runtime-object.cc78
-rw-r--r--chromium/v8/src/runtime/runtime-regexp.cc604
-rw-r--r--chromium/v8/src/runtime/runtime-strings.cc24
-rw-r--r--chromium/v8/src/runtime/runtime-test.cc194
-rw-r--r--chromium/v8/src/runtime/runtime-typedarray.cc242
-rw-r--r--chromium/v8/src/runtime/runtime-wasm.cc79
-rw-r--r--chromium/v8/src/runtime/runtime.h89
21 files changed, 1001 insertions, 1200 deletions
diff --git a/chromium/v8/src/runtime/runtime-array.cc b/chromium/v8/src/runtime/runtime-array.cc
index 07c6ad01168..97432b6ef19 100644
--- a/chromium/v8/src/runtime/runtime-array.cc
+++ b/chromium/v8/src/runtime/runtime-array.cc
@@ -17,20 +17,6 @@
namespace v8 {
namespace internal {
-RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) {
- HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
- Object* length = prototype->length();
- CHECK(length->IsSmi());
- CHECK(Smi::cast(length)->value() == 0);
- CHECK(prototype->HasFastSmiOrObjectElements());
- // This is necessary to enable fast checks for absence of elements
- // on Array.prototype and below.
- prototype->set_elements(isolate->heap()->empty_fixed_array());
- return Smi::kZero;
-}
-
static void InstallCode(
Isolate* isolate, Handle<JSObject> holder, const char* name,
Handle<Code> code, int argc = -1,
diff --git a/chromium/v8/src/runtime/runtime-atomics.cc b/chromium/v8/src/runtime/runtime-atomics.cc
index ff7ded9b090..62986c66618 100644
--- a/chromium/v8/src/runtime/runtime-atomics.cc
+++ b/chromium/v8/src/runtime/runtime-atomics.cc
@@ -19,13 +19,14 @@ namespace internal {
namespace {
-inline bool AtomicIsLockFree(uint32_t size) {
- return size == 1 || size == 2 || size == 4;
-}
-
#if V8_CC_GNU
template <typename T>
+inline T ExchangeSeqCst(T* p, T value) {
+ return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST);
+}
+
+template <typename T>
inline T CompareExchangeSeqCst(T* p, T oldval, T newval) {
(void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
@@ -57,24 +58,28 @@ inline T XorSeqCst(T* p, T value) {
return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST);
}
-template <typename T>
-inline T ExchangeSeqCst(T* p, T value) {
- return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST);
-}
-
#elif V8_CC_MSVC
-#define InterlockedCompareExchange32 _InterlockedCompareExchange
#define InterlockedExchange32 _InterlockedExchange
+#define InterlockedCompareExchange32 _InterlockedCompareExchange
+#define InterlockedCompareExchange8 _InterlockedCompareExchange8
#define InterlockedExchangeAdd32 _InterlockedExchangeAdd
+#define InterlockedExchangeAdd16 _InterlockedExchangeAdd16
+#define InterlockedExchangeAdd8 _InterlockedExchangeAdd8
#define InterlockedAnd32 _InterlockedAnd
#define InterlockedOr32 _InterlockedOr
#define InterlockedXor32 _InterlockedXor
-#define InterlockedExchangeAdd16 _InterlockedExchangeAdd16
-#define InterlockedCompareExchange8 _InterlockedCompareExchange8
-#define InterlockedExchangeAdd8 _InterlockedExchangeAdd8
#define ATOMIC_OPS(type, suffix, vctype) \
+ inline type ExchangeSeqCst(type* p, type value) { \
+ return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \
+ bit_cast<vctype>(value)); \
+ } \
+ 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 AddSeqCst(type* p, type value) { \
return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \
bit_cast<vctype>(value)); \
@@ -94,16 +99,6 @@ inline T ExchangeSeqCst(T* p, T 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)); \
- } \
- \
- inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \
- return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \
- bit_cast<vctype>(newval), \
- bit_cast<vctype>(oldval)); \
}
ATOMIC_OPS(int8_t, 8, char)
@@ -116,15 +111,15 @@ ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */
#undef ATOMIC_OPS_INTEGER
#undef ATOMIC_OPS
-#undef InterlockedCompareExchange32
#undef InterlockedExchange32
+#undef InterlockedCompareExchange32
+#undef InterlockedCompareExchange8
#undef InterlockedExchangeAdd32
+#undef InterlockedExchangeAdd16
+#undef InterlockedExchangeAdd8
#undef InterlockedAnd32
#undef InterlockedOr32
#undef InterlockedXor32
-#undef InterlockedExchangeAdd16
-#undef InterlockedCompareExchange8
-#undef InterlockedExchangeAdd8
#else
@@ -176,16 +171,21 @@ inline Object* ToObject(Isolate* isolate, uint16_t t) {
return Smi::FromInt(t);
}
-
inline Object* ToObject(Isolate* isolate, int32_t t) {
return *isolate->factory()->NewNumber(t);
}
-
inline Object* ToObject(Isolate* isolate, uint32_t t) {
return *isolate->factory()->NewNumber(t);
}
+template <typename T>
+inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index,
+ Handle<Object> obj) {
+ T value = FromObject<T>(obj);
+ T result = ExchangeSeqCst(static_cast<T*>(buffer) + index, value);
+ return ToObject(isolate, result);
+}
template <typename T>
inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index,
@@ -197,7 +197,6 @@ inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index,
return ToObject(isolate, result);
}
-
template <typename T>
inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index,
Handle<Object> obj) {
@@ -206,7 +205,6 @@ inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index,
return ToObject(isolate, result);
}
-
template <typename T>
inline Object* DoSub(Isolate* isolate, void* buffer, size_t index,
Handle<Object> obj) {
@@ -215,7 +213,6 @@ inline Object* DoSub(Isolate* isolate, void* buffer, size_t index,
return ToObject(isolate, result);
}
-
template <typename T>
inline Object* DoAnd(Isolate* isolate, void* buffer, size_t index,
Handle<Object> obj) {
@@ -224,7 +221,6 @@ inline Object* DoAnd(Isolate* isolate, void* buffer, size_t index,
return ToObject(isolate, result);
}
-
template <typename T>
inline Object* DoOr(Isolate* isolate, void* buffer, size_t index,
Handle<Object> obj) {
@@ -233,7 +229,6 @@ inline Object* DoOr(Isolate* isolate, void* buffer, size_t index,
return ToObject(isolate, result);
}
-
template <typename T>
inline Object* DoXor(Isolate* isolate, void* buffer, size_t index,
Handle<Object> obj) {
@@ -242,75 +237,6 @@ inline Object* DoXor(Isolate* isolate, void* buffer, size_t index,
return ToObject(isolate, result);
}
-
-template <typename T>
-inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index,
- Handle<Object> obj) {
- T value = FromObject<T>(obj);
- T result = ExchangeSeqCst(static_cast<T*>(buffer) + index, value);
- return ToObject(isolate, result);
-}
-
-
-// Uint8Clamped functions
-
-uint8_t ClampToUint8(int32_t value) {
- if (value < 0) return 0;
- if (value > 255) return 255;
- return value;
-}
-
-
-inline Object* DoCompareExchangeUint8Clamped(Isolate* isolate, void* buffer,
- size_t index,
- Handle<Object> oldobj,
- Handle<Object> newobj) {
- typedef int32_t convert_type;
- uint8_t oldval = ClampToUint8(FromObject<convert_type>(oldobj));
- uint8_t newval = ClampToUint8(FromObject<convert_type>(newobj));
- uint8_t result = CompareExchangeSeqCst(static_cast<uint8_t*>(buffer) + index,
- oldval, newval);
- return ToObject(isolate, result);
-}
-
-
-#define DO_UINT8_CLAMPED_OP(name, op) \
- inline Object* Do##name##Uint8Clamped(Isolate* isolate, void* buffer, \
- size_t index, Handle<Object> obj) { \
- typedef int32_t convert_type; \
- uint8_t* p = static_cast<uint8_t*>(buffer) + index; \
- convert_type operand = FromObject<convert_type>(obj); \
- uint8_t expected; \
- uint8_t result; \
- do { \
- expected = *p; \
- result = ClampToUint8(static_cast<convert_type>(expected) op operand); \
- } while (CompareExchangeSeqCst(p, expected, result) != expected); \
- return ToObject(isolate, expected); \
- }
-
-DO_UINT8_CLAMPED_OP(Add, +)
-DO_UINT8_CLAMPED_OP(Sub, -)
-DO_UINT8_CLAMPED_OP(And, &)
-DO_UINT8_CLAMPED_OP(Or, | )
-DO_UINT8_CLAMPED_OP(Xor, ^)
-
-#undef DO_UINT8_CLAMPED_OP
-
-
-inline Object* DoExchangeUint8Clamped(Isolate* isolate, void* buffer,
- size_t index, Handle<Object> obj) {
- typedef int32_t convert_type;
- uint8_t* p = static_cast<uint8_t*>(buffer) + index;
- uint8_t result = ClampToUint8(FromObject<convert_type>(obj));
- uint8_t expected;
- do {
- expected = *p;
- } while (CompareExchangeSeqCst(p, expected, result) != expected);
- return ToObject(isolate, expected);
-}
-
-
} // anonymous namespace
// Duplicated from objects.h
@@ -347,13 +273,12 @@ RUNTIME_FUNCTION(Runtime_ThrowInvalidAtomicAccessIndexError) {
isolate, NewRangeError(MessageTemplate::kInvalidAtomicAccessIndex));
}
-RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) {
+RUNTIME_FUNCTION(Runtime_AtomicsExchange) {
HandleScope scope(isolate);
- DCHECK_EQ(4, args.length());
+ DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
CONVERT_SIZE_ARG_CHECKED(index, 1);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
CHECK(sta->GetBuffer()->is_shared());
CHECK_LT(index, NumberToSize(sta->length()));
@@ -363,15 +288,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) {
switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
case kExternal##Type##Array: \
- return DoCompareExchange<ctype>(isolate, source, index, oldobj, newobj);
+ return DoExchange<ctype>(isolate, source, index, value);
INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- case kExternalUint8ClampedArray:
- return DoCompareExchangeUint8Clamped(isolate, source, index, oldobj,
- newobj);
-
default:
break;
}
@@ -380,13 +301,13 @@ RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) {
return isolate->heap()->undefined_value();
}
-
-RUNTIME_FUNCTION(Runtime_AtomicsAdd) {
+RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) {
HandleScope scope(isolate);
- DCHECK_EQ(3, args.length());
+ DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
CONVERT_SIZE_ARG_CHECKED(index, 1);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3);
CHECK(sta->GetBuffer()->is_shared());
CHECK_LT(index, NumberToSize(sta->length()));
@@ -396,14 +317,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsAdd) {
switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
case kExternal##Type##Array: \
- return DoAdd<ctype>(isolate, source, index, value);
+ return DoCompareExchange<ctype>(isolate, source, index, oldobj, newobj);
INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- case kExternalUint8ClampedArray:
- return DoAddUint8Clamped(isolate, source, index, value);
-
default:
break;
}
@@ -412,8 +330,9 @@ RUNTIME_FUNCTION(Runtime_AtomicsAdd) {
return isolate->heap()->undefined_value();
}
-
-RUNTIME_FUNCTION(Runtime_AtomicsSub) {
+// ES #sec-atomics.add
+// Atomics.add( typedArray, index, value )
+RUNTIME_FUNCTION(Runtime_AtomicsAdd) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
@@ -428,14 +347,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsSub) {
switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
case kExternal##Type##Array: \
- return DoSub<ctype>(isolate, source, index, value);
+ return DoAdd<ctype>(isolate, source, index, value);
INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- case kExternalUint8ClampedArray:
- return DoSubUint8Clamped(isolate, source, index, value);
-
default:
break;
}
@@ -444,8 +360,9 @@ RUNTIME_FUNCTION(Runtime_AtomicsSub) {
return isolate->heap()->undefined_value();
}
-
-RUNTIME_FUNCTION(Runtime_AtomicsAnd) {
+// ES #sec-atomics.sub
+// Atomics.sub( typedArray, index, value )
+RUNTIME_FUNCTION(Runtime_AtomicsSub) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
@@ -460,14 +377,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsAnd) {
switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
case kExternal##Type##Array: \
- return DoAnd<ctype>(isolate, source, index, value);
+ return DoSub<ctype>(isolate, source, index, value);
INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- case kExternalUint8ClampedArray:
- return DoAndUint8Clamped(isolate, source, index, value);
-
default:
break;
}
@@ -476,8 +390,9 @@ RUNTIME_FUNCTION(Runtime_AtomicsAnd) {
return isolate->heap()->undefined_value();
}
-
-RUNTIME_FUNCTION(Runtime_AtomicsOr) {
+// ES #sec-atomics.and
+// Atomics.and( typedArray, index, value )
+RUNTIME_FUNCTION(Runtime_AtomicsAnd) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
@@ -492,14 +407,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsOr) {
switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
case kExternal##Type##Array: \
- return DoOr<ctype>(isolate, source, index, value);
+ return DoAnd<ctype>(isolate, source, index, value);
INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- case kExternalUint8ClampedArray:
- return DoOrUint8Clamped(isolate, source, index, value);
-
default:
break;
}
@@ -508,8 +420,9 @@ RUNTIME_FUNCTION(Runtime_AtomicsOr) {
return isolate->heap()->undefined_value();
}
-
-RUNTIME_FUNCTION(Runtime_AtomicsXor) {
+// ES #sec-atomics.or
+// Atomics.or( typedArray, index, value )
+RUNTIME_FUNCTION(Runtime_AtomicsOr) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
@@ -524,14 +437,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsXor) {
switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
case kExternal##Type##Array: \
- return DoXor<ctype>(isolate, source, index, value);
+ return DoOr<ctype>(isolate, source, index, value);
INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- case kExternalUint8ClampedArray:
- return DoXorUint8Clamped(isolate, source, index, value);
-
default:
break;
}
@@ -540,8 +450,9 @@ RUNTIME_FUNCTION(Runtime_AtomicsXor) {
return isolate->heap()->undefined_value();
}
-
-RUNTIME_FUNCTION(Runtime_AtomicsExchange) {
+// ES #sec-atomics.xor
+// Atomics.xor( typedArray, index, value )
+RUNTIME_FUNCTION(Runtime_AtomicsXor) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
@@ -556,14 +467,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsExchange) {
switch (sta->type()) {
#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
case kExternal##Type##Array: \
- return DoExchange<ctype>(isolate, source, index, value);
+ return DoXor<ctype>(isolate, source, index, value);
INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- case kExternalUint8ClampedArray:
- return DoExchangeUint8Clamped(isolate, source, index, value);
-
default:
break;
}
@@ -572,13 +480,5 @@ RUNTIME_FUNCTION(Runtime_AtomicsExchange) {
return isolate->heap()->undefined_value();
}
-
-RUNTIME_FUNCTION(Runtime_AtomicsIsLockFree) {
- HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(size, 0);
- uint32_t usize = NumberToUint32(*size);
- return isolate->heap()->ToBoolean(AtomicIsLockFree(usize));
-}
} // namespace internal
} // namespace v8
diff --git a/chromium/v8/src/runtime/runtime-classes.cc b/chromium/v8/src/runtime/runtime-classes.cc
index 9398586de5f..7dadca5026c 100644
--- a/chromium/v8/src/runtime/runtime-classes.cc
+++ b/chromium/v8/src/runtime/runtime-classes.cc
@@ -52,6 +52,13 @@ RUNTIME_FUNCTION(Runtime_ThrowSuperAlreadyCalledError) {
isolate, NewReferenceError(MessageTemplate::kSuperAlreadyCalled));
}
+RUNTIME_FUNCTION(Runtime_ThrowSuperNotCalled) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(0, args.length());
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewReferenceError(MessageTemplate::kSuperNotCalled));
+}
+
namespace {
Object* ThrowNotSuperConstructor(Isolate* isolate, Handle<Object> constructor,
diff --git a/chromium/v8/src/runtime/runtime-compiler.cc b/chromium/v8/src/runtime/runtime-compiler.cc
index f929d736977..b7151f83c64 100644
--- a/chromium/v8/src/runtime/runtime-compiler.cc
+++ b/chromium/v8/src/runtime/runtime-compiler.cc
@@ -41,19 +41,6 @@ RUNTIME_FUNCTION(Runtime_CompileLazy) {
return function->code();
}
-RUNTIME_FUNCTION(Runtime_CompileBaseline) {
- HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- StackLimitCheck check(isolate);
- if (check.JsHasOverflowed(1 * KB)) return isolate->StackOverflow();
- if (!Compiler::CompileBaseline(function)) {
- return isolate->heap()->exception();
- }
- DCHECK(function->is_compiled());
- return function->code();
-}
-
RUNTIME_FUNCTION(Runtime_CompileOptimized_Concurrent) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
@@ -213,14 +200,9 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
if (!activations_finder.has_code_activations_) {
- if (function->code() == *optimized_code) {
- if (FLAG_trace_deopt) {
- PrintF("[removing optimized code for: ");
- function->PrintName();
- PrintF("]\n");
- }
- function->ReplaceCode(function->shared()->code());
- }
+ Deoptimizer::UnlinkOptimizedCode(*optimized_code,
+ function->context()->native_context());
+
// Evict optimized code for this function from the cache so that it
// doesn't get used for new closures.
function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
@@ -348,9 +330,6 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
ast_id.ToInt(), data->OsrPcOffset()->value());
}
- // TODO(titzer): this is a massive hack to make the deopt counts
- // match. Fix heuristics for reenabling optimizations!
- function->shared()->increment_deopt_count();
if (result->is_turbofanned()) {
// When we're waiting for concurrent optimization, set to compile on
diff --git a/chromium/v8/src/runtime/runtime-debug.cc b/chromium/v8/src/runtime/runtime-debug.cc
index 3649621b099..a13d3f95ccc 100644
--- a/chromium/v8/src/runtime/runtime-debug.cc
+++ b/chromium/v8/src/runtime/runtime-debug.cc
@@ -68,7 +68,7 @@ RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
if (isolate->debug()->break_points_active()) {
- isolate->debug()->HandleDebugBreak();
+ isolate->debug()->HandleDebugBreak(kIgnoreIfTopFrameBlackboxed);
}
return isolate->heap()->undefined_value();
}
@@ -1312,7 +1312,7 @@ RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
// 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())) {
+ while ((heap_obj = iterator.next()) != nullptr) {
if (!heap_obj->IsJSObject()) continue;
JSObject* obj = JSObject::cast(heap_obj);
if (obj->IsJSContextExtensionObject()) continue;
@@ -1365,7 +1365,7 @@ RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
{
HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
HeapObject* heap_obj;
- while ((heap_obj = iterator.next())) {
+ while ((heap_obj = iterator.next()) != nullptr) {
if (!heap_obj->IsJSObject()) continue;
JSObject* obj = JSObject::cast(heap_obj);
if (obj->map()->GetConstructor() != *constructor) continue;
@@ -1904,7 +1904,12 @@ RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
// Collect coverage data.
- std::unique_ptr<Coverage> coverage(Coverage::Collect(isolate, false));
+ std::unique_ptr<Coverage> coverage;
+ if (isolate->is_best_effort_code_coverage()) {
+ coverage.reset(Coverage::CollectBestEffort(isolate));
+ } else {
+ coverage.reset(Coverage::CollectPrecise(isolate));
+ }
Factory* factory = isolate->factory();
// Turn the returned data structure into JavaScript.
// Create an array of scripts.
@@ -1945,7 +1950,8 @@ RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
SealHandleScope shs(isolate);
CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
- Coverage::TogglePrecise(isolate, enable);
+ Coverage::SelectMode(isolate, enable ? debug::Coverage::kPreciseCount
+ : debug::Coverage::kBestEffort);
return isolate->heap()->undefined_value();
}
diff --git a/chromium/v8/src/runtime/runtime-forin.cc b/chromium/v8/src/runtime/runtime-forin.cc
index 9a7c5398651..08f6d868192 100644
--- a/chromium/v8/src/runtime/runtime-forin.cc
+++ b/chromium/v8/src/runtime/runtime-forin.cc
@@ -31,7 +31,7 @@ MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) {
if (!accumulator.is_receiver_simple_enum()) {
Handle<FixedArray> keys;
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, keys, accumulator.GetKeys(GetKeysConversion::kKeepNumbers),
+ isolate, keys, accumulator.GetKeys(GetKeysConversion::kConvertToString),
HeapObject);
// Test again, since cache may have been built by GetKeys() calls above.
if (!accumulator.is_receiver_simple_enum()) return keys;
diff --git a/chromium/v8/src/runtime/runtime-futex.cc b/chromium/v8/src/runtime/runtime-futex.cc
index b6582ffc7f9..5c2106e6859 100644
--- a/chromium/v8/src/runtime/runtime-futex.cc
+++ b/chromium/v8/src/runtime/runtime-futex.cc
@@ -17,44 +17,6 @@
namespace v8 {
namespace internal {
-RUNTIME_FUNCTION(Runtime_AtomicsWait) {
- HandleScope scope(isolate);
- DCHECK_EQ(4, args.length());
- 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);
- CHECK(sta->GetBuffer()->is_shared());
- CHECK_LT(index, NumberToSize(sta->length()));
- CHECK_EQ(sta->type(), kExternalInt32Array);
- CHECK(timeout == V8_INFINITY || !std::isnan(timeout));
-
- if (!isolate->allow_atomics_wait()) {
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewTypeError(MessageTemplate::kAtomicsWaitNotAllowed));
- }
-
- Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
- size_t addr = (index << 2) + NumberToSize(sta->byte_offset());
-
- return FutexEmulation::Wait(isolate, array_buffer, addr, value, timeout);
-}
-
-RUNTIME_FUNCTION(Runtime_AtomicsWake) {
- HandleScope scope(isolate);
- DCHECK_EQ(3, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
- CONVERT_SIZE_ARG_CHECKED(index, 1);
- CONVERT_UINT32_ARG_CHECKED(count, 2);
- CHECK(sta->GetBuffer()->is_shared());
- CHECK_LT(index, NumberToSize(sta->length()));
- CHECK_EQ(sta->type(), kExternalInt32Array);
-
- Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
- size_t addr = (index << 2) + NumberToSize(sta->byte_offset());
-
- return FutexEmulation::Wake(isolate, array_buffer, addr, count);
-}
RUNTIME_FUNCTION(Runtime_AtomicsNumWaitersForTesting) {
HandleScope scope(isolate);
diff --git a/chromium/v8/src/runtime/runtime-generator.cc b/chromium/v8/src/runtime/runtime-generator.cc
index 96486736e12..0c8fe6db011 100644
--- a/chromium/v8/src/runtime/runtime-generator.cc
+++ b/chromium/v8/src/runtime/runtime-generator.cc
@@ -77,6 +77,36 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetInputOrDebugPos) {
return generator->input_or_debug_pos();
}
+RUNTIME_FUNCTION(Runtime_AsyncGeneratorGetAwaitInputOrDebugPos) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(JSAsyncGeneratorObject, generator, 0);
+
+ return generator->await_input_or_debug_pos();
+}
+
+RUNTIME_FUNCTION(Runtime_AsyncGeneratorResolve) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(3, args.length());
+
+ // Runtime call is implemented in InterpreterIntrinsics and lowered in
+ // JSIntrinsicLowering
+ UNREACHABLE();
+
+ return isolate->heap()->undefined_value();
+}
+
+RUNTIME_FUNCTION(Runtime_AsyncGeneratorReject) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(2, args.length());
+
+ // Runtime call is implemented in InterpreterIntrinsics and lowered in
+ // JSIntrinsicLowering
+ UNREACHABLE();
+
+ return isolate->heap()->undefined_value();
+}
+
RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
diff --git a/chromium/v8/src/runtime/runtime-i18n.cc b/chromium/v8/src/runtime/runtime-i18n.cc
index e89175a37db..80c8a9cd012 100644
--- a/chromium/v8/src/runtime/runtime-i18n.cc
+++ b/chromium/v8/src/runtime/runtime-i18n.cc
@@ -15,7 +15,6 @@
#include "src/i18n.h"
#include "src/isolate-inl.h"
#include "src/messages.h"
-#include "src/string-case.h"
#include "src/utils.h"
#include "unicode/brkiter.h"
@@ -30,7 +29,6 @@
#include "unicode/fieldpos.h"
#include "unicode/fpositer.h"
#include "unicode/locid.h"
-#include "unicode/normalizer2.h"
#include "unicode/numfmt.h"
#include "unicode/numsys.h"
#include "unicode/rbbi.h"
@@ -49,24 +47,6 @@
namespace v8 {
namespace internal {
-namespace {
-
-const UChar* GetUCharBufferFromFlat(const String::FlatContent& flat,
- std::unique_ptr<uc16[]>* dest,
- int32_t length) {
- DCHECK(flat.IsFlat());
- if (flat.IsOneByte()) {
- if (!*dest) {
- dest->reset(NewArray<uc16>(length));
- CopyChars(dest->get(), flat.ToOneByteVector().start(), length);
- }
- return reinterpret_cast<const UChar*>(dest->get());
- } else {
- return reinterpret_cast<const UChar*>(flat.ToUC16Vector().start());
- }
-}
-
-} // namespace
// ECMA 402 6.2.3
RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
@@ -322,13 +302,13 @@ RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
- // Set date time formatter as internal field of the resulting JS object.
+ // Set date time formatter as embedder field of the resulting JS object.
icu::SimpleDateFormat* date_format =
DateFormat::InitializeDateTimeFormat(isolate, locale, options, resolved);
if (!date_format) return isolate->ThrowIllegalOperation();
- local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
+ local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(date_format));
// Make object handle weak so we can delete the data format once GC kicks in.
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
@@ -512,13 +492,13 @@ RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
- // Set number formatter as internal field of the resulting JS object.
+ // Set number formatter as embedder field of the resulting JS object.
icu::DecimalFormat* number_format =
NumberFormat::InitializeNumberFormat(isolate, locale, options, resolved);
if (!number_format) return isolate->ThrowIllegalOperation();
- local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
+ local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(number_format));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
@@ -552,6 +532,29 @@ RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
result.length())));
}
+RUNTIME_FUNCTION(Runtime_CurrencyDigits) {
+ DCHECK_EQ(1, args.length());
+
+ CONVERT_ARG_HANDLE_CHECKED(String, currency, 0);
+
+ // TODO(littledan): Avoid transcoding the string twice
+ v8::String::Utf8Value currency_string(v8::Utils::ToLocal(currency));
+ icu::UnicodeString currency_icu =
+ icu::UnicodeString::fromUTF8(*currency_string);
+
+ DisallowHeapAllocation no_gc;
+ UErrorCode status = U_ZERO_ERROR;
+#if U_ICU_VERSION_MAJOR_NUM >= 59
+ uint32_t fraction_digits = ucurr_getDefaultFractionDigits(
+ icu::toUCharPtr(currency_icu.getTerminatedBuffer()), &status);
+#else
+ uint32_t fraction_digits = ucurr_getDefaultFractionDigits(
+ currency_icu.getTerminatedBuffer(), &status);
+#endif
+ // For missing currency codes, default to the most common, 2
+ if (!U_SUCCESS(status)) fraction_digits = 2;
+ return Smi::FromInt(fraction_digits);
+}
RUNTIME_FUNCTION(Runtime_CreateCollator) {
HandleScope scope(isolate);
@@ -569,13 +572,13 @@ RUNTIME_FUNCTION(Runtime_CreateCollator) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
- // Set collator as internal field of the resulting JS object.
+ // Set collator as embedder field of the resulting JS object.
icu::Collator* collator =
Collator::InitializeCollator(isolate, locale, options, resolved);
if (!collator) return isolate->ThrowIllegalOperation();
- local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
+ local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(collator));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
@@ -622,64 +625,6 @@ RUNTIME_FUNCTION(Runtime_InternalCompare) {
}
-RUNTIME_FUNCTION(Runtime_StringNormalize) {
- HandleScope scope(isolate);
- static const struct {
- const char* name;
- UNormalization2Mode mode;
- } normalizationForms[] = {
- {"nfc", UNORM2_COMPOSE},
- {"nfc", UNORM2_DECOMPOSE},
- {"nfkc", UNORM2_COMPOSE},
- {"nfkc", UNORM2_DECOMPOSE},
- };
-
- DCHECK_EQ(2, args.length());
-
- CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
- CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
- CHECK(form_id >= 0 &&
- static_cast<size_t>(form_id) < arraysize(normalizationForms));
-
- int length = s->length();
- s = String::Flatten(s);
- icu::UnicodeString result;
- std::unique_ptr<uc16[]> sap;
- UErrorCode status = U_ZERO_ERROR;
- {
- DisallowHeapAllocation no_gc;
- String::FlatContent flat = s->GetFlatContent();
- const UChar* src = GetUCharBufferFromFlat(flat, &sap, length);
- icu::UnicodeString input(false, src, length);
- // Getting a singleton. Should not free it.
- const icu::Normalizer2* normalizer =
- icu::Normalizer2::getInstance(nullptr, normalizationForms[form_id].name,
- normalizationForms[form_id].mode, status);
- DCHECK(U_SUCCESS(status));
- CHECK(normalizer != nullptr);
- int32_t normalized_prefix_length =
- normalizer->spanQuickCheckYes(input, status);
- // Quick return if the input is already normalized.
- if (length == normalized_prefix_length) return *s;
- icu::UnicodeString unnormalized =
- input.tempSubString(normalized_prefix_length);
- // Read-only alias of the normalized prefix.
- result.setTo(false, input.getBuffer(), normalized_prefix_length);
- // copy-on-write; normalize the suffix and append to |result|.
- normalizer->normalizeSecondAndAppend(result, unnormalized, status);
- }
-
- if (U_FAILURE(status)) {
- return isolate->heap()->undefined_value();
- }
-
- RETURN_RESULT_OR_FAILURE(
- isolate, isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length())));
-}
-
-
RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
HandleScope scope(isolate);
@@ -696,15 +641,15 @@ RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
- // Set break iterator as internal field of the resulting JS object.
+ // Set break iterator as embedder field of the resulting JS object.
icu::BreakIterator* break_iterator = V8BreakIterator::InitializeBreakIterator(
isolate, locale, options, resolved);
if (!break_iterator) return isolate->ThrowIllegalOperation();
- local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
+ local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(break_iterator));
// Make sure that the pointer to adopted text is NULL.
- local_object->SetInternalField(1, static_cast<Smi*>(nullptr));
+ local_object->SetEmbedderField(1, static_cast<Smi*>(nullptr));
// Make object handle weak so we can delete the break iterator once GC kicks
// in.
@@ -729,7 +674,7 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
CHECK_NOT_NULL(break_iterator);
icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
- break_iterator_holder->GetInternalField(1));
+ break_iterator_holder->GetEmbedderField(1));
delete u_text;
int length = text->length();
@@ -739,7 +684,7 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
std::unique_ptr<uc16[]> sap;
const UChar* text_value = GetUCharBufferFromFlat(flat, &sap, length);
u_text = new icu::UnicodeString(text_value, length);
- break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
+ break_iterator_holder->SetEmbedderField(1, reinterpret_cast<Smi*>(u_text));
break_iterator->setText(*u_text);
@@ -823,295 +768,6 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
}
}
-namespace {
-MUST_USE_RESULT Object* LocaleConvertCase(Handle<String> s, Isolate* isolate,
- bool is_to_upper, const char* lang) {
- auto case_converter = is_to_upper ? u_strToUpper : u_strToLower;
- int32_t src_length = s->length();
- int32_t dest_length = src_length;
- UErrorCode status;
- Handle<SeqTwoByteString> result;
- std::unique_ptr<uc16[]> sap;
-
- if (dest_length == 0) return isolate->heap()->empty_string();
-
- // This is not a real loop. It'll be executed only once (no overflow) or
- // twice (overflow).
- for (int i = 0; i < 2; ++i) {
- // Case conversion can increase the string length (e.g. sharp-S => SS) so
- // that we have to handle RangeError exceptions here.
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, isolate->factory()->NewRawTwoByteString(dest_length));
- DisallowHeapAllocation no_gc;
- DCHECK(s->IsFlat());
- String::FlatContent flat = s->GetFlatContent();
- const UChar* src = GetUCharBufferFromFlat(flat, &sap, src_length);
- status = U_ZERO_ERROR;
- dest_length = case_converter(reinterpret_cast<UChar*>(result->GetChars()),
- dest_length, src, src_length, lang, &status);
- if (status != U_BUFFER_OVERFLOW_ERROR) break;
- }
-
- // In most cases, the output will fill the destination buffer completely
- // leading to an unterminated string (U_STRING_NOT_TERMINATED_WARNING).
- // Only in rare cases, it'll be shorter than the destination buffer and
- // |result| has to be truncated.
- DCHECK(U_SUCCESS(status));
- if (V8_LIKELY(status == U_STRING_NOT_TERMINATED_WARNING)) {
- DCHECK(dest_length == result->length());
- return *result;
- }
- if (U_SUCCESS(status)) {
- DCHECK(dest_length < result->length());
- return *Handle<SeqTwoByteString>::cast(
- SeqString::Truncate(result, dest_length));
- }
- return *s;
-}
-
-inline bool IsASCIIUpper(uint16_t ch) { return ch >= 'A' && ch <= 'Z'; }
-
-const uint8_t kToLower[256] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
- 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
- 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
- 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
- 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
- 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
- 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
- 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
- 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xD7,
- 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3,
- 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB,
- 0xFC, 0xFD, 0xFE, 0xFF,
-};
-
-inline uint16_t ToLatin1Lower(uint16_t ch) {
- return static_cast<uint16_t>(kToLower[ch]);
-}
-
-inline uint16_t ToASCIIUpper(uint16_t ch) {
- return ch & ~((ch >= 'a' && ch <= 'z') << 5);
-}
-
-// Does not work for U+00DF (sharp-s), U+00B5 (micron), U+00FF.
-inline uint16_t ToLatin1Upper(uint16_t ch) {
- DCHECK(ch != 0xDF && ch != 0xB5 && ch != 0xFF);
- return ch &
- ~(((ch >= 'a' && ch <= 'z') || (((ch & 0xE0) == 0xE0) && ch != 0xF7))
- << 5);
-}
-
-template <typename Char>
-bool ToUpperFastASCII(const Vector<const Char>& src,
- Handle<SeqOneByteString> result) {
- // Do a faster loop for the case where all the characters are ASCII.
- uint16_t ored = 0;
- int32_t index = 0;
- for (auto it = src.begin(); it != src.end(); ++it) {
- uint16_t ch = static_cast<uint16_t>(*it);
- ored |= ch;
- result->SeqOneByteStringSet(index++, ToASCIIUpper(ch));
- }
- return !(ored & ~0x7F);
-}
-
-const uint16_t sharp_s = 0xDF;
-
-template <typename Char>
-bool ToUpperOneByte(const Vector<const Char>& src, uint8_t* dest,
- int* sharp_s_count) {
- // Still pretty-fast path for the input with non-ASCII Latin-1 characters.
-
- // There are two special cases.
- // 1. U+00B5 and U+00FF are mapped to a character beyond U+00FF.
- // 2. Lower case sharp-S converts to "SS" (two characters)
- *sharp_s_count = 0;
- for (auto it = src.begin(); it != src.end(); ++it) {
- uint16_t ch = static_cast<uint16_t>(*it);
- if (V8_UNLIKELY(ch == sharp_s)) {
- ++(*sharp_s_count);
- continue;
- }
- if (V8_UNLIKELY(ch == 0xB5 || ch == 0xFF)) {
- // Since this upper-cased character does not fit in an 8-bit string, we
- // need to take the 16-bit path.
- return false;
- }
- *dest++ = ToLatin1Upper(ch);
- }
-
- return true;
-}
-
-template <typename Char>
-void ToUpperWithSharpS(const Vector<const Char>& src,
- Handle<SeqOneByteString> result) {
- int32_t dest_index = 0;
- for (auto it = src.begin(); it != src.end(); ++it) {
- uint16_t ch = static_cast<uint16_t>(*it);
- if (ch == sharp_s) {
- result->SeqOneByteStringSet(dest_index++, 'S');
- result->SeqOneByteStringSet(dest_index++, 'S');
- } else {
- result->SeqOneByteStringSet(dest_index++, ToLatin1Upper(ch));
- }
- }
-}
-
-inline int FindFirstUpperOrNonAscii(Handle<String> s, int length) {
- for (int index = 0; index < length; ++index) {
- uint16_t ch = s->Get(index);
- if (V8_UNLIKELY(IsASCIIUpper(ch) || ch & ~0x7F)) {
- return index;
- }
- }
- return length;
-}
-
-MUST_USE_RESULT Object* ConvertToLower(Handle<String> s, Isolate* isolate) {
- if (!s->HasOnlyOneByteChars()) {
- // Use a slower implementation for strings with characters beyond U+00FF.
- return LocaleConvertCase(s, isolate, false, "");
- }
-
- int length = s->length();
-
- // We depend here on the invariant that the length of a Latin1
- // string is invariant under ToLowerCase, and the result always
- // fits in the Latin1 range in the *root locale*. It does not hold
- // for ToUpperCase even in the root locale.
-
- // Scan the string for uppercase and non-ASCII characters for strings
- // shorter than a machine-word without any memory allocation overhead.
- // TODO(jshin): Apply this to a longer input by breaking FastAsciiConvert()
- // to two parts, one for scanning the prefix with no change and the other for
- // handling ASCII-only characters.
- int index_to_first_unprocessed = length;
- const bool is_short = length < static_cast<int>(sizeof(uintptr_t));
- if (is_short) {
- index_to_first_unprocessed = FindFirstUpperOrNonAscii(s, length);
- // Nothing to do if the string is all ASCII with no uppercase.
- if (index_to_first_unprocessed == length) return *s;
- }
-
- Handle<SeqOneByteString> result =
- isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
-
- DisallowHeapAllocation no_gc;
- DCHECK(s->IsFlat());
- String::FlatContent flat = s->GetFlatContent();
- uint8_t* dest = result->GetChars();
- if (flat.IsOneByte()) {
- const uint8_t* src = flat.ToOneByteVector().start();
- bool has_changed_character = false;
- index_to_first_unprocessed = FastAsciiConvert<true>(
- reinterpret_cast<char*>(dest), reinterpret_cast<const char*>(src),
- length, &has_changed_character);
- // If not ASCII, we keep the result up to index_to_first_unprocessed and
- // process the rest.
- if (index_to_first_unprocessed == length)
- return has_changed_character ? *result : *s;
-
- for (int index = index_to_first_unprocessed; index < length; ++index) {
- dest[index] = ToLatin1Lower(static_cast<uint16_t>(src[index]));
- }
- } else {
- if (index_to_first_unprocessed == length) {
- DCHECK(!is_short);
- index_to_first_unprocessed = FindFirstUpperOrNonAscii(s, length);
- }
- // Nothing to do if the string is all ASCII with no uppercase.
- if (index_to_first_unprocessed == length) return *s;
- const uint16_t* src = flat.ToUC16Vector().start();
- CopyChars(dest, src, index_to_first_unprocessed);
- for (int index = index_to_first_unprocessed; index < length; ++index) {
- dest[index] = ToLatin1Lower(static_cast<uint16_t>(src[index]));
- }
- }
-
- return *result;
-}
-
-MUST_USE_RESULT Object* ConvertToUpper(Handle<String> s, Isolate* isolate) {
- int32_t length = s->length();
- if (s->HasOnlyOneByteChars() && length > 0) {
- Handle<SeqOneByteString> result =
- isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
-
- DCHECK(s->IsFlat());
- int sharp_s_count;
- bool is_result_single_byte;
- {
- DisallowHeapAllocation no_gc;
- String::FlatContent flat = s->GetFlatContent();
- uint8_t* dest = result->GetChars();
- if (flat.IsOneByte()) {
- Vector<const uint8_t> src = flat.ToOneByteVector();
- bool has_changed_character = false;
- int index_to_first_unprocessed =
- FastAsciiConvert<false>(reinterpret_cast<char*>(result->GetChars()),
- reinterpret_cast<const char*>(src.start()),
- length, &has_changed_character);
- if (index_to_first_unprocessed == length)
- return has_changed_character ? *result : *s;
- // If not ASCII, we keep the result up to index_to_first_unprocessed and
- // process the rest.
- is_result_single_byte =
- ToUpperOneByte(src.SubVector(index_to_first_unprocessed, length),
- dest + index_to_first_unprocessed, &sharp_s_count);
- } else {
- DCHECK(flat.IsTwoByte());
- Vector<const uint16_t> src = flat.ToUC16Vector();
- if (ToUpperFastASCII(src, result)) return *result;
- is_result_single_byte = ToUpperOneByte(src, dest, &sharp_s_count);
- }
- }
-
- // Go to the full Unicode path if there are characters whose uppercase
- // is beyond the Latin-1 range (cannot be represented in OneByteString).
- if (V8_UNLIKELY(!is_result_single_byte)) {
- return LocaleConvertCase(s, isolate, true, "");
- }
-
- if (sharp_s_count == 0) return *result;
-
- // We have sharp_s_count sharp-s characters, but the result is still
- // in the Latin-1 range.
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- isolate->factory()->NewRawOneByteString(length + sharp_s_count));
- DisallowHeapAllocation no_gc;
- String::FlatContent flat = s->GetFlatContent();
- if (flat.IsOneByte()) {
- ToUpperWithSharpS(flat.ToOneByteVector(), result);
- } else {
- ToUpperWithSharpS(flat.ToUC16Vector(), result);
- }
-
- return *result;
- }
-
- return LocaleConvertCase(s, isolate, true, "");
-}
-
-MUST_USE_RESULT Object* ConvertCase(Handle<String> s, bool is_upper,
- Isolate* isolate) {
- return is_upper ? ConvertToUpper(s, isolate) : ConvertToLower(s, isolate);
-}
-
-} // namespace
-
RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 1);
diff --git a/chromium/v8/src/runtime/runtime-internal.cc b/chromium/v8/src/runtime/runtime-internal.cc
index 83995098c0a..8c566c081db 100644
--- a/chromium/v8/src/runtime/runtime-internal.cc
+++ b/chromium/v8/src/runtime/runtime-internal.cc
@@ -95,21 +95,70 @@ RUNTIME_FUNCTION(Runtime_ThrowSymbolAsyncIteratorInvalid) {
isolate, NewTypeError(MessageTemplate::kSymbolAsyncIteratorInvalid));
}
+#define THROW_ERROR(isolate, args, call) \
+ HandleScope scope(isolate); \
+ DCHECK_LE(1, args.length()); \
+ CONVERT_SMI_ARG_CHECKED(message_id_smi, 0); \
+ \
+ Handle<Object> undefined = isolate->factory()->undefined_value(); \
+ Handle<Object> arg0 = (args.length() > 1) ? args.at(1) : undefined; \
+ Handle<Object> arg1 = (args.length() > 2) ? args.at(2) : undefined; \
+ Handle<Object> arg2 = (args.length() > 3) ? args.at(3) : undefined; \
+ \
+ MessageTemplate::Template message_id = \
+ static_cast<MessageTemplate::Template>(message_id_smi); \
+ \
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, call(message_id, arg0, arg1, arg2));
+
+RUNTIME_FUNCTION(Runtime_ThrowRangeError) {
+ THROW_ERROR(isolate, args, NewRangeError);
+}
+
RUNTIME_FUNCTION(Runtime_ThrowTypeError) {
+ THROW_ERROR(isolate, args, NewTypeError);
+}
+
+#undef THROW_ERROR
+
+namespace {
+
+const char* ElementsKindToType(ElementsKind fixed_elements_kind) {
+ switch (fixed_elements_kind) {
+#define ELEMENTS_KIND_CASE(Type, type, TYPE, ctype, size) \
+ case TYPE##_ELEMENTS: \
+ return #Type "Array";
+
+ TYPED_ARRAYS(ELEMENTS_KIND_CASE)
+#undef ELEMENTS_KIND_CASE
+
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+} // namespace
+
+RUNTIME_FUNCTION(Runtime_ThrowInvalidTypedArrayAlignment) {
HandleScope scope(isolate);
- DCHECK_LE(1, args.length());
- CONVERT_SMI_ARG_CHECKED(message_id_smi, 0);
+ DCHECK_EQ(2, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Map, map, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, problem_string, 1);
- Handle<Object> undefined = isolate->factory()->undefined_value();
- Handle<Object> arg0 = (args.length() > 1) ? args.at(1) : undefined;
- Handle<Object> arg1 = (args.length() > 2) ? args.at(2) : undefined;
- Handle<Object> arg2 = (args.length() > 3) ? args.at(3) : undefined;
+ ElementsKind kind = map->elements_kind();
- MessageTemplate::Template message_id =
- static_cast<MessageTemplate::Template>(message_id_smi);
+ Handle<String> type =
+ isolate->factory()->NewStringFromAsciiChecked(ElementsKindToType(kind));
- THROW_NEW_ERROR_RETURN_FAILURE(isolate,
- NewTypeError(message_id, arg0, arg1, arg2));
+ ExternalArrayType external_type =
+ isolate->factory()->GetArrayTypeFromElementsKind(kind);
+ size_t size = isolate->factory()->GetExternalArrayElementSize(external_type);
+ Handle<Object> element_size =
+ handle(Smi::FromInt(static_cast<int>(size)), isolate);
+
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayAlignment,
+ problem_string, type, element_size));
}
RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) {
@@ -367,7 +416,7 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) {
MessageLocation location;
if (ComputeLocation(isolate, &location)) {
std::unique_ptr<ParseInfo> info(new ParseInfo(location.shared()));
- if (parsing::ParseAny(info.get())) {
+ if (parsing::ParseAny(info.get(), isolate)) {
CallPrinter printer(isolate, location.shared()->IsUserJavaScript());
Handle<String> str = printer.Print(info->literal(), location.start_pos());
if (str->length() > 0) return str;
diff --git a/chromium/v8/src/runtime/runtime-liveedit.cc b/chromium/v8/src/runtime/runtime-liveedit.cc
index 56493252c8f..fa49df88dad 100644
--- a/chromium/v8/src/runtime/runtime-liveedit.cc
+++ b/chromium/v8/src/runtime/runtime-liveedit.cc
@@ -32,7 +32,7 @@ RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
{
HeapIterator iterator(heap);
HeapObject* heap_obj;
- while ((heap_obj = iterator.next())) {
+ while ((heap_obj = iterator.next()) != nullptr) {
if (!heap_obj->IsSharedFunctionInfo()) continue;
SharedFunctionInfo* shared = SharedFunctionInfo::cast(heap_obj);
if (shared->script() != *script) continue;
diff --git a/chromium/v8/src/runtime/runtime-maths.cc b/chromium/v8/src/runtime/runtime-maths.cc
index 4cb4f006ff3..bb8436cd110 100644
--- a/chromium/v8/src/runtime/runtime-maths.cc
+++ b/chromium/v8/src/runtime/runtime-maths.cc
@@ -41,10 +41,18 @@ RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
cache = Handle<FixedDoubleArray>::cast(
isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
native_context->set_math_random_cache(*cache);
- // Initialize state if not yet initialized.
- while (state0 == 0 || state1 == 0) {
- isolate->random_number_generator()->NextBytes(&state0, sizeof(state0));
- isolate->random_number_generator()->NextBytes(&state1, sizeof(state1));
+ // Initialize state if not yet initialized. If a fixed random seed was
+ // requested, use it to reset our state the first time a script asks for
+ // random numbers in this context. This ensures the script sees a consistent
+ // sequence.
+ if (FLAG_random_seed != 0) {
+ state0 = FLAG_random_seed;
+ state1 = FLAG_random_seed;
+ } else {
+ while (state0 == 0 || state1 == 0) {
+ isolate->random_number_generator()->NextBytes(&state0, sizeof(state0));
+ isolate->random_number_generator()->NextBytes(&state1, sizeof(state1));
+ }
}
}
diff --git a/chromium/v8/src/runtime/runtime-module.cc b/chromium/v8/src/runtime/runtime-module.cc
index f36a09b410b..3c896d8c566 100644
--- a/chromium/v8/src/runtime/runtime-module.cc
+++ b/chromium/v8/src/runtime/runtime-module.cc
@@ -13,9 +13,36 @@ namespace internal {
RUNTIME_FUNCTION(Runtime_DynamicImportCall) {
HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- // TODO(gsathya): Implement ImportCall.
- return isolate->heap()->undefined_value();
+ DCHECK_EQ(2, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, specifier, 1);
+
+ Handle<JSPromise> promise = isolate->factory()->NewJSPromise();
+
+ Handle<String> specifier_str;
+ MaybeHandle<String> maybe_specifier = Object::ToString(isolate, specifier);
+ if (!maybe_specifier.ToHandle(&specifier_str)) {
+ DCHECK(isolate->has_pending_exception());
+ Handle<Object> reason(isolate->pending_exception(), isolate);
+ isolate->clear_pending_exception();
+
+ Handle<Object> argv[] = {promise, reason,
+ isolate->factory()->ToBoolean(false)};
+
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
+ isolate->factory()->undefined_value(),
+ arraysize(argv), argv))
+ return *promise;
+ }
+ DCHECK(!isolate->has_pending_exception());
+
+ Handle<Script> script(Script::cast(function->shared()->script()));
+ Handle<String> source_url(String::cast(script->name()));
+
+ isolate->RunHostImportModuleDynamicallyCallback(source_url, specifier_str,
+ promise);
+ return *promise;
}
RUNTIME_FUNCTION(Runtime_GetModuleNamespace) {
diff --git a/chromium/v8/src/runtime/runtime-numbers.cc b/chromium/v8/src/runtime/runtime-numbers.cc
index 4d8d5d267db..72d2403c173 100644
--- a/chromium/v8/src/runtime/runtime-numbers.cc
+++ b/chromium/v8/src/runtime/runtime-numbers.cc
@@ -213,13 +213,6 @@ RUNTIME_FUNCTION(Runtime_IsSmi) {
}
-RUNTIME_FUNCTION(Runtime_GetRootNaN) {
- SealHandleScope shs(isolate);
- DCHECK_EQ(0, args.length());
- return isolate->heap()->nan_value();
-}
-
-
RUNTIME_FUNCTION(Runtime_GetHoleNaNUpper) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
diff --git a/chromium/v8/src/runtime/runtime-object.cc b/chromium/v8/src/runtime/runtime-object.cc
index dd24728457d..4c34b0e563f 100644
--- a/chromium/v8/src/runtime/runtime-object.cc
+++ b/chromium/v8/src/runtime/runtime-object.cc
@@ -50,20 +50,21 @@ static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
//
// Additionally, we need to make sure that we do not cache results
// for objects that require access checks.
+
+ // Convert string-index keys to their number variant to avoid internalization
+ // below; and speed up subsequent conversion to index.
+ uint32_t index;
+ if (key_obj->IsString() && String::cast(*key_obj)->AsArrayIndex(&index)) {
+ key_obj = isolate->factory()->NewNumberFromUint(index);
+ }
if (receiver_obj->IsJSObject()) {
if (!receiver_obj->IsJSGlobalProxy() &&
!receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
- DisallowHeapAllocation no_allocation;
Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
Handle<Name> key = Handle<Name>::cast(key_obj);
- // Get to a ThinString's referenced internalized string, but don't
- // otherwise force internalization. We assume that internalization
- // (which is a dictionary lookup with a non-internalized key) is
- // about as expensive as doing the property dictionary lookup with
- // the non-internalized key directly.
- if (key->IsThinString()) {
- key = handle(Handle<ThinString>::cast(key)->actual(), isolate);
- }
+ key_obj = key = isolate->factory()->InternalizeName(key);
+
+ DisallowHeapAllocation no_allocation;
if (receiver->IsJSGlobalObject()) {
// Attempt dictionary lookup.
GlobalDictionary* dictionary = receiver->global_dictionary();
@@ -215,6 +216,23 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
return isolate->heap()->false_value();
}
+RUNTIME_FUNCTION(Runtime_AddDictionaryProperty) {
+ HandleScope scope(isolate);
+ Handle<JSObject> receiver = args.at<JSObject>(0);
+ Handle<Name> name = args.at<Name>(1);
+ Handle<Object> value = args.at(2);
+
+ DCHECK(name->IsUniqueName());
+
+ Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
+ int entry;
+ PropertyDetails property_details(kData, NONE, 0, PropertyCellType::kNoCell);
+ dictionary =
+ NameDictionary::Add(dictionary, name, value, property_details, &entry);
+ receiver->set_properties(*dictionary);
+ return *value;
+}
+
// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
// TODO(verwaest): Support the common cases with precached map directly in
// an Object.create stub.
@@ -648,12 +666,12 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
if (name->IsUniqueName()) {
nexus.ConfigureMonomorphic(name, handle(object->map()));
} else {
- nexus.ConfigureMegamorphic();
+ nexus.ConfigureMegamorphic(PROPERTY);
}
} else if (nexus.ic_state() == MONOMORPHIC) {
if (nexus.FindFirstMap() != object->map() ||
nexus.GetFeedbackExtra() != *name) {
- nexus.ConfigureMegamorphic();
+ nexus.ConfigureMegamorphic(PROPERTY);
}
}
@@ -680,6 +698,28 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
return *object;
}
+RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(3, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Smi, position, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
+ CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 2);
+
+ DCHECK(FLAG_type_profile);
+
+ Handle<String> type = Object::TypeOf(isolate, value);
+ if (value->IsJSReceiver()) {
+ Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
+ type = JSReceiver::GetConstructorName(object);
+ }
+
+ DCHECK(vector->metadata()->HasTypeProfileSlot());
+ CollectTypeProfileNexus nexus(vector, vector->GetTypeProfileSlot());
+ nexus.Collect(type, position->value());
+
+ return isolate->heap()->undefined_value();
+}
+
// Return property without being observable by accessors or interceptors.
RUNTIME_FUNCTION(Runtime_GetDataProperty) {
HandleScope scope(isolate);
@@ -988,6 +1028,22 @@ RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
return *value;
}
+// Checks that 22.2.2.1.1 Runtime Semantics: IterableToList produces exactly the
+// same result as doing nothing.
+RUNTIME_FUNCTION(Runtime_IterableToListCanBeElided) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
+
+ if (!obj->IsJSObject()) return isolate->heap()->ToBoolean(false);
+
+ // While iteration alone may not have observable side-effects, calling
+ // toNumber on an object will. Make sure the arg is not an array of objects.
+ ElementsKind kind = JSObject::cast(*obj)->GetElementsKind();
+ if (!IsFastNumberElementsKind(kind)) return isolate->heap()->ToBoolean(false);
+
+ return isolate->heap()->ToBoolean(!obj->IterationHasObservableEffects());
+}
} // namespace internal
} // namespace v8
diff --git a/chromium/v8/src/runtime/runtime-regexp.cc b/chromium/v8/src/runtime/runtime-regexp.cc
index aec95565109..c9f201c11d5 100644
--- a/chromium/v8/src/runtime/runtime-regexp.cc
+++ b/chromium/v8/src/runtime/runtime-regexp.cc
@@ -4,6 +4,8 @@
#include "src/runtime/runtime-utils.h"
+#include <functional>
+
#include "src/arguments.h"
#include "src/conversions-inl.h"
#include "src/isolate-inl.h"
@@ -17,14 +19,45 @@
namespace v8 {
namespace internal {
+namespace {
+
+// Looks up the capture of the given name. Returns the (1-based) numbered
+// capture index or -1 on failure.
+int LookupNamedCapture(std::function<bool(String*)> name_matches,
+ FixedArray* capture_name_map) {
+ // TODO(jgruber): Sort capture_name_map and do binary search via
+ // internalized strings.
+
+ int maybe_capture_index = -1;
+ const int named_capture_count = capture_name_map->length() >> 1;
+ for (int j = 0; j < named_capture_count; j++) {
+ // The format of {capture_name_map} is documented at
+ // JSRegExp::kIrregexpCaptureNameMapIndex.
+ const int name_ix = j * 2;
+ const int index_ix = j * 2 + 1;
+
+ String* capture_name = String::cast(capture_name_map->get(name_ix));
+ if (!name_matches(capture_name)) continue;
+
+ maybe_capture_index = Smi::cast(capture_name_map->get(index_ix))->value();
+ break;
+ }
+
+ return maybe_capture_index;
+}
+
+} // namespace
+
class CompiledReplacement {
public:
explicit CompiledReplacement(Zone* zone)
: parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
- // Return whether the replacement is simple.
- bool Compile(Handle<String> replacement, int capture_count,
- int subject_length);
+ // Return whether the replacement is simple. Can also fail and return Nothing
+ // if the given replacement string is invalid (and requires throwing a
+ // SyntaxError).
+ Maybe<bool> Compile(Handle<JSRegExp> regexp, Handle<String> replacement,
+ int capture_count, int subject_length);
// Use Apply only if Compile returned false.
void Apply(ReplacementStringBuilder* builder, int match_from, int match_to,
@@ -91,9 +124,17 @@ class CompiledReplacement {
};
template <typename Char>
- bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
- Vector<Char> characters, int capture_count,
- int subject_length, Zone* zone) {
+ Maybe<bool> ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
+ Vector<Char> characters,
+ FixedArray* capture_name_map,
+ int capture_count, int subject_length,
+ Zone* zone) {
+ // Equivalent to String::GetSubstitution, except that this method converts
+ // the replacement string into an internal representation that avoids
+ // repeated parsing when used repeatedly.
+ DCHECK_IMPLIES(capture_name_map != nullptr,
+ FLAG_harmony_regexp_named_captures);
+
int length = characters.length();
int last = 0;
for (int i = 0; i < length; i++) {
@@ -181,6 +222,57 @@ class CompiledReplacement {
i = next_index;
break;
}
+ case '<': {
+ if (capture_name_map == nullptr) {
+ i = next_index;
+ break;
+ }
+
+ // Scan until the next '>', throwing a SyntaxError exception if one
+ // is not found, and let the enclosed substring be groupName.
+
+ const int name_start_index = next_index + 1;
+ int closing_bracket_index = -1;
+ for (int j = name_start_index; j < length; j++) {
+ if (characters[j] == '>') {
+ closing_bracket_index = j;
+ break;
+ }
+ }
+
+ // Throw a SyntaxError for invalid replacement strings.
+ if (closing_bracket_index == -1) return Nothing<bool>();
+
+ Vector<Char> requested_name =
+ characters.SubVector(name_start_index, closing_bracket_index);
+
+ // Let capture be ? Get(namedCaptures, groupName).
+
+ const int capture_index = LookupNamedCapture(
+ [=](String* capture_name) {
+ return capture_name->IsEqualTo(requested_name);
+ },
+ capture_name_map);
+
+ // If ? HasProperty(_namedCaptures_, _groupName_) is *false*, throw
+ // a *SyntaxError* exception.
+ if (capture_index == -1) return Nothing<bool>();
+
+ // If capture is undefined, replace the text through the following
+ // '>' with the empty string.
+ // Otherwise, replace the text through the following '>' with
+ // ? ToString(capture).
+
+ DCHECK(1 <= capture_index && capture_index <= capture_count);
+
+ if (i > last) {
+ parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
+ }
+ parts->Add(ReplacementPart::SubjectCapture(capture_index), zone);
+ last = closing_bracket_index + 1;
+ i = closing_bracket_index;
+ break;
+ }
default:
i = next_index;
break;
@@ -190,12 +282,12 @@ class CompiledReplacement {
if (length > last) {
if (last == 0) {
// Replacement is simple. Do not use Apply to do the replacement.
- return true;
+ return Just(true);
} else {
parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
}
}
- return false;
+ return Just(false);
}
ZoneList<ReplacementPart> parts_;
@@ -203,23 +295,37 @@ class CompiledReplacement {
Zone* zone_;
};
-
-bool CompiledReplacement::Compile(Handle<String> replacement, int capture_count,
- int subject_length) {
+Maybe<bool> CompiledReplacement::Compile(Handle<JSRegExp> regexp,
+ Handle<String> replacement,
+ int capture_count,
+ int subject_length) {
{
DisallowHeapAllocation no_gc;
String::FlatContent content = replacement->GetFlatContent();
DCHECK(content.IsFlat());
- bool simple = false;
+
+ FixedArray* capture_name_map = nullptr;
+ if (capture_count > 0) {
+ DCHECK_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
+ Object* maybe_capture_name_map = regexp->CaptureNameMap();
+ if (maybe_capture_name_map->IsFixedArray()) {
+ DCHECK(FLAG_harmony_regexp_named_captures);
+ capture_name_map = FixedArray::cast(maybe_capture_name_map);
+ }
+ }
+
+ Maybe<bool> simple = Nothing<bool>();
if (content.IsOneByte()) {
simple = ParseReplacementPattern(&parts_, content.ToOneByteVector(),
- capture_count, subject_length, zone());
+ capture_name_map, capture_count,
+ subject_length, zone());
} else {
DCHECK(content.IsTwoByte());
simple = ParseReplacementPattern(&parts_, content.ToUC16Vector(),
- capture_count, subject_length, zone());
+ capture_name_map, capture_count,
+ subject_length, zone());
}
- if (simple) return true;
+ if (simple.IsNothing() || simple.FromJust()) return simple;
}
Isolate* isolate = replacement->GetIsolate();
@@ -241,7 +347,7 @@ bool CompiledReplacement::Compile(Handle<String> replacement, int capture_count,
substring_index++;
}
}
- return false;
+ return Just(false);
}
@@ -489,14 +595,30 @@ MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
int capture_count = regexp->CaptureCount();
int subject_length = subject->length();
+ JSRegExp::Type typeTag = regexp->TypeTag();
+ if (typeTag == JSRegExp::IRREGEXP) {
+ // Ensure the RegExp is compiled so we can access the capture-name map.
+ if (RegExpImpl::IrregexpPrepare(regexp, subject) == -1) {
+ DCHECK(isolate->has_pending_exception());
+ return isolate->heap()->exception();
+ }
+ }
+
// CompiledReplacement uses zone allocation.
Zone zone(isolate->allocator(), ZONE_NAME);
CompiledReplacement compiled_replacement(&zone);
- bool simple_replace =
- compiled_replacement.Compile(replacement, capture_count, subject_length);
+ Maybe<bool> maybe_simple_replace = compiled_replacement.Compile(
+ regexp, replacement, capture_count, subject_length);
+ if (maybe_simple_replace.IsNothing()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewSyntaxError(MessageTemplate::kRegExpInvalidReplaceString,
+ replacement));
+ }
+
+ const bool simple_replace = maybe_simple_replace.FromJust();
// Shortcut for simple non-regexp global replacements
- if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
+ if (typeTag == JSRegExp::ATOM && simple_replace) {
if (subject->HasOnlyOneByteChars() && replacement->HasOnlyOneByteChars()) {
return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
isolate, subject, regexp, replacement, last_match_info);
@@ -647,7 +769,7 @@ MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
Heap* heap = isolate->heap();
// The trimming is performed on a newly allocated object, which is on a
- // fresly allocated page or on an already swept page. Hence, the sweeper
+ // freshly allocated page or on an already swept page. Hence, the sweeper
// thread can not get confused with the filler creation. No synchronization
// needed.
// TODO(hpayer): We should shrink the large object page if the size
@@ -841,23 +963,28 @@ namespace {
class MatchInfoBackedMatch : public String::Match {
public:
- MatchInfoBackedMatch(Isolate* isolate, Handle<String> subject,
+ MatchInfoBackedMatch(Isolate* isolate, Handle<JSRegExp> regexp,
+ Handle<String> subject,
Handle<RegExpMatchInfo> match_info)
: isolate_(isolate), match_info_(match_info) {
subject_ = String::Flatten(subject);
+
+ if (regexp->TypeTag() == JSRegExp::IRREGEXP) {
+ Object* o = regexp->CaptureNameMap();
+ has_named_captures_ = o->IsFixedArray();
+ if (has_named_captures_) {
+ DCHECK(FLAG_harmony_regexp_named_captures);
+ capture_name_map_ = handle(FixedArray::cast(o));
+ }
+ } else {
+ has_named_captures_ = false;
+ }
}
Handle<String> GetMatch() override {
return RegExpUtils::GenericCaptureGetter(isolate_, match_info_, 0, nullptr);
}
- MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
- Handle<Object> capture_obj = RegExpUtils::GenericCaptureGetter(
- isolate_, match_info_, i, capture_exists);
- return (*capture_exists) ? Object::ToString(isolate_, capture_obj)
- : isolate_->factory()->empty_string();
- }
-
Handle<String> GetPrefix() override {
const int match_start = match_info_->Capture(0);
return isolate_->factory()->NewSubString(subject_, 0, match_start);
@@ -869,32 +996,90 @@ class MatchInfoBackedMatch : public String::Match {
subject_->length());
}
+ bool HasNamedCaptures() override { return has_named_captures_; }
+
int CaptureCount() override {
return match_info_->NumberOfCaptureRegisters() / 2;
}
- virtual ~MatchInfoBackedMatch() {}
+ MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
+ Handle<Object> capture_obj = RegExpUtils::GenericCaptureGetter(
+ isolate_, match_info_, i, capture_exists);
+ return (*capture_exists) ? Object::ToString(isolate_, capture_obj)
+ : isolate_->factory()->empty_string();
+ }
+
+ MaybeHandle<String> GetNamedCapture(Handle<String> name,
+ CaptureState* state) override {
+ DCHECK(has_named_captures_);
+ const int capture_index = LookupNamedCapture(
+ [=](String* capture_name) { return capture_name->Equals(*name); },
+ *capture_name_map_);
+
+ if (capture_index == -1) {
+ *state = INVALID;
+ return name; // Arbitrary string handle.
+ }
+
+ DCHECK(1 <= capture_index && capture_index <= CaptureCount());
+
+ bool capture_exists;
+ Handle<String> capture_value;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_value,
+ GetCapture(capture_index, &capture_exists),
+ String);
+
+ if (!capture_exists) {
+ *state = UNMATCHED;
+ return isolate_->factory()->empty_string();
+ } else {
+ *state = MATCHED;
+ return capture_value;
+ }
+ }
private:
Isolate* isolate_;
Handle<String> subject_;
Handle<RegExpMatchInfo> match_info_;
+
+ bool has_named_captures_;
+ Handle<FixedArray> capture_name_map_;
};
class VectorBackedMatch : public String::Match {
public:
VectorBackedMatch(Isolate* isolate, Handle<String> subject,
Handle<String> match, int match_position,
- ZoneVector<Handle<Object>>* captures)
+ ZoneVector<Handle<Object>>* captures,
+ Handle<Object> groups_obj)
: isolate_(isolate),
match_(match),
match_position_(match_position),
captures_(captures) {
subject_ = String::Flatten(subject);
+
+ DCHECK(groups_obj->IsUndefined(isolate) || groups_obj->IsJSReceiver());
+ has_named_captures_ = !groups_obj->IsUndefined(isolate);
+ if (has_named_captures_) groups_obj_ = Handle<JSReceiver>::cast(groups_obj);
}
Handle<String> GetMatch() override { return match_; }
+ Handle<String> GetPrefix() override {
+ return isolate_->factory()->NewSubString(subject_, 0, match_position_);
+ }
+
+ Handle<String> GetSuffix() override {
+ const int match_end_position = match_position_ + match_->length();
+ return isolate_->factory()->NewSubString(subject_, match_end_position,
+ subject_->length());
+ }
+
+ bool HasNamedCaptures() override { return has_named_captures_; }
+
+ int CaptureCount() override { return static_cast<int>(captures_->size()); }
+
MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
Handle<Object> capture_obj = captures_->at(i);
if (capture_obj->IsUndefined(isolate_)) {
@@ -905,19 +1090,30 @@ class VectorBackedMatch : public String::Match {
return Object::ToString(isolate_, capture_obj);
}
- Handle<String> GetPrefix() override {
- return isolate_->factory()->NewSubString(subject_, 0, match_position_);
- }
+ MaybeHandle<String> GetNamedCapture(Handle<String> name,
+ CaptureState* state) override {
+ DCHECK(has_named_captures_);
- Handle<String> GetSuffix() override {
- const int match_end_position = match_position_ + match_->length();
- return isolate_->factory()->NewSubString(subject_, match_end_position,
- subject_->length());
- }
+ Maybe<bool> maybe_capture_exists =
+ JSReceiver::HasProperty(groups_obj_, name);
+ if (maybe_capture_exists.IsNothing()) return MaybeHandle<String>();
- int CaptureCount() override { return static_cast<int>(captures_->size()); }
+ if (!maybe_capture_exists.FromJust()) {
+ *state = INVALID;
+ return name; // Arbitrary string handle.
+ }
- virtual ~VectorBackedMatch() {}
+ Handle<Object> capture_obj;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_obj,
+ Object::GetProperty(groups_obj_, name), String);
+ if (capture_obj->IsUndefined(isolate_)) {
+ *state = UNMATCHED;
+ return isolate_->factory()->empty_string();
+ } else {
+ *state = MATCHED;
+ return Object::ToString(isolate_, capture_obj);
+ }
+ }
private:
Isolate* isolate_;
@@ -925,8 +1121,37 @@ class VectorBackedMatch : public String::Match {
Handle<String> match_;
const int match_position_;
ZoneVector<Handle<Object>>* captures_;
+
+ bool has_named_captures_;
+ Handle<JSReceiver> groups_obj_;
};
+// Create the groups object (see also the RegExp result creation in
+// RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo).
+Handle<JSObject> ConstructNamedCaptureGroupsObject(
+ Isolate* isolate, Handle<FixedArray> capture_map,
+ std::function<Object*(int)> f_get_capture) {
+ DCHECK(FLAG_harmony_regexp_named_captures);
+ Handle<JSObject> groups = isolate->factory()->NewJSObjectWithNullProto();
+
+ const int capture_count = capture_map->length() >> 1;
+ for (int i = 0; i < capture_count; i++) {
+ const int name_ix = i * 2;
+ const int index_ix = i * 2 + 1;
+
+ Handle<String> capture_name(String::cast(capture_map->get(name_ix)));
+ const int capture_ix = Smi::cast(capture_map->get(index_ix))->value();
+ DCHECK(1 <= capture_ix && capture_ix <= capture_count);
+
+ Handle<Object> capture_value(f_get_capture(capture_ix), isolate);
+ DCHECK(capture_value->IsUndefined(isolate) || capture_value->IsString());
+
+ JSObject::AddProperty(groups, capture_name, capture_value, NONE);
+ }
+
+ return groups;
+}
+
// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
// separate last match info. See comment on that function.
template <bool has_capture>
@@ -934,8 +1159,9 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject,
Handle<JSRegExp> regexp,
Handle<RegExpMatchInfo> last_match_array,
Handle<JSArray> result_array) {
- DCHECK(subject->IsFlat());
+ DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
DCHECK_NE(has_capture, regexp->CaptureCount() == 0);
+ DCHECK(subject->IsFlat());
int capture_count = regexp->CaptureCount();
int subject_length = subject->length();
@@ -1013,11 +1239,20 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject,
if (has_capture) {
// Arguments array to replace function is match, captures, index and
- // subject, i.e., 3 + capture count in total.
- Handle<FixedArray> elements =
- isolate->factory()->NewFixedArray(3 + capture_count);
+ // subject, i.e., 3 + capture count in total. If the RegExp contains
+ // named captures, they are also passed as the last argument.
+
+ Handle<Object> maybe_capture_map(regexp->CaptureNameMap(), isolate);
+ const bool has_named_captures = maybe_capture_map->IsFixedArray();
+ DCHECK_IMPLIES(has_named_captures, FLAG_harmony_regexp_named_captures);
- elements->set(0, *match);
+ const int argc =
+ has_named_captures ? 4 + capture_count : 3 + capture_count;
+
+ Handle<FixedArray> elements = isolate->factory()->NewFixedArray(argc);
+ int cursor = 0;
+
+ elements->set(cursor++, *match);
for (int i = 1; i <= capture_count; i++) {
int start = current_match[i * 2];
if (start >= 0) {
@@ -1025,14 +1260,25 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject,
DCHECK(start <= end);
Handle<String> substring =
isolate->factory()->NewSubString(subject, start, end);
- elements->set(i, *substring);
+ elements->set(cursor++, *substring);
} else {
DCHECK(current_match[i * 2 + 1] < 0);
- elements->set(i, isolate->heap()->undefined_value());
+ elements->set(cursor++, isolate->heap()->undefined_value());
}
}
- elements->set(capture_count + 1, Smi::FromInt(match_start));
- elements->set(capture_count + 2, *subject);
+
+ elements->set(cursor++, Smi::FromInt(match_start));
+ elements->set(cursor++, *subject);
+
+ if (has_named_captures) {
+ Handle<FixedArray> capture_map =
+ Handle<FixedArray>::cast(maybe_capture_map);
+ Handle<JSObject> groups = ConstructNamedCaptureGroupsObject(
+ isolate, capture_map, [=](int ix) { return elements->get(ix); });
+ elements->set(cursor++, *groups);
+ }
+
+ DCHECK_EQ(cursor, argc);
builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
} else {
builder.Add(*match);
@@ -1078,107 +1324,22 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject,
}
}
-MUST_USE_RESULT MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction(
- Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
- Handle<Object> replace_obj) {
- Factory* factory = isolate->factory();
- Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
-
- const int flags = regexp->GetFlags();
-
- DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
- DCHECK_EQ(flags & JSRegExp::kGlobal, 0);
-
- // TODO(jgruber): This should be an easy port to CSA with massive payback.
-
- const bool sticky = (flags & JSRegExp::kSticky) != 0;
- uint32_t last_index = 0;
- if (sticky) {
- Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
- ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
- Object::ToLength(isolate, last_index_obj),
- String);
- last_index = PositiveNumberToUint32(*last_index_obj);
-
- if (static_cast<int>(last_index) > subject->length()) last_index = 0;
- }
-
- Handle<Object> match_indices_obj;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, match_indices_obj,
- RegExpImpl::Exec(regexp, subject, last_index, last_match_info), String);
-
- if (match_indices_obj->IsNull(isolate)) {
- if (sticky) regexp->SetLastIndex(0);
- return subject;
- }
-
- Handle<RegExpMatchInfo> match_indices =
- Handle<RegExpMatchInfo>::cast(match_indices_obj);
-
- const int index = match_indices->Capture(0);
- const int end_of_match = match_indices->Capture(1);
-
- if (sticky) regexp->SetLastIndex(end_of_match);
-
- IncrementalStringBuilder builder(isolate);
- builder.AppendString(factory->NewSubString(subject, 0, index));
-
- // Compute the parameter list consisting of the match, captures, index,
- // and subject for the replace function invocation.
- // The number of captures plus one for the match.
- const int m = match_indices->NumberOfCaptureRegisters() / 2;
-
- const int argc = m + 2;
- ScopedVector<Handle<Object>> argv(argc);
-
- for (int j = 0; j < m; j++) {
- bool ok;
- Handle<String> capture =
- RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
- if (ok) {
- argv[j] = capture;
- } else {
- argv[j] = factory->undefined_value();
- }
- }
-
- argv[argc - 2] = handle(Smi::FromInt(index), isolate);
- argv[argc - 1] = subject;
-
- Handle<Object> replacement_obj;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, replacement_obj,
- Execution::Call(isolate, replace_obj, factory->undefined_value(), argc,
- argv.start()),
- String);
-
- Handle<String> replacement;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, replacement, Object::ToString(isolate, replacement_obj), String);
-
- builder.AppendString(replacement);
- builder.AppendString(
- factory->NewSubString(subject, end_of_match, subject->length()));
-
- return builder.Finish();
-}
-
// Legacy implementation of RegExp.prototype[Symbol.replace] which
// doesn't properly call the underlying exec method.
MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate,
Handle<JSRegExp> regexp,
Handle<String> string,
Handle<Object> replace_obj) {
+ // Functional fast-paths are dispatched directly by replace builtin.
+ DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
+ DCHECK(!replace_obj->IsCallable());
+
Factory* factory = isolate->factory();
const int flags = regexp->GetFlags();
const bool global = (flags & JSRegExp::kGlobal) != 0;
const bool sticky = (flags & JSRegExp::kSticky) != 0;
- // Functional fast-paths are dispatched directly by replace builtin.
- DCHECK(!replace_obj->IsCallable());
-
Handle<String> replace;
ASSIGN_RETURN_ON_EXCEPTION(isolate, replace,
Object::ToString(isolate, replace_obj), String);
@@ -1221,7 +1382,7 @@ MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate,
builder.AppendString(factory->NewSubString(string, 0, start_index));
if (replace->length() > 0) {
- MatchInfoBackedMatch m(isolate, string, match_indices);
+ MatchInfoBackedMatch m(isolate, regexp, string, match_indices);
Handle<String> replacement;
ASSIGN_RETURN_ON_EXCEPTION(isolate, replacement,
String::GetSubstitution(isolate, &m, replace),
@@ -1293,56 +1454,118 @@ RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
-
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, replace_obj, 2);
DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
+ DCHECK(replace_obj->map()->is_callable());
- RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction(
- isolate, subject, regexp, replace));
-}
+ Factory* factory = isolate->factory();
+ Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
-namespace {
+ const int flags = regexp->GetFlags();
+ DCHECK_EQ(flags & JSRegExp::kGlobal, 0);
+
+ // TODO(jgruber): This should be an easy port to CSA with massive payback.
+
+ const bool sticky = (flags & JSRegExp::kSticky) != 0;
+ uint32_t last_index = 0;
+ if (sticky) {
+ Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, last_index_obj, Object::ToLength(isolate, last_index_obj));
+ last_index = PositiveNumberToUint32(*last_index_obj);
-// ES##sec-speciesconstructor
-// SpeciesConstructor ( O, defaultConstructor )
-MUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor(
- Isolate* isolate, Handle<JSReceiver> recv,
- Handle<JSFunction> default_ctor) {
- Handle<Object> ctor_obj;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, ctor_obj,
- JSObject::GetProperty(recv, isolate->factory()->constructor_string()),
- Object);
+ if (static_cast<int>(last_index) > subject->length()) last_index = 0;
+ }
- if (ctor_obj->IsUndefined(isolate)) return default_ctor;
+ Handle<Object> match_indices_obj;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, match_indices_obj,
+ RegExpImpl::Exec(regexp, subject, last_index, last_match_info));
- if (!ctor_obj->IsJSReceiver()) {
- THROW_NEW_ERROR(isolate,
- NewTypeError(MessageTemplate::kConstructorNotReceiver),
- Object);
+ if (match_indices_obj->IsNull(isolate)) {
+ if (sticky) regexp->SetLastIndex(0);
+ return *subject;
}
- Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
+ Handle<RegExpMatchInfo> match_indices =
+ Handle<RegExpMatchInfo>::cast(match_indices_obj);
+
+ const int index = match_indices->Capture(0);
+ const int end_of_match = match_indices->Capture(1);
- Handle<Object> species;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, species,
- JSObject::GetProperty(ctor, isolate->factory()->species_symbol()),
- Object);
+ if (sticky) regexp->SetLastIndex(end_of_match);
- if (species->IsNullOrUndefined(isolate)) {
- return default_ctor;
+ IncrementalStringBuilder builder(isolate);
+ builder.AppendString(factory->NewSubString(subject, 0, index));
+
+ // Compute the parameter list consisting of the match, captures, index,
+ // and subject for the replace function invocation. If the RegExp contains
+ // named captures, they are also passed as the last argument.
+
+ // The number of captures plus one for the match.
+ const int m = match_indices->NumberOfCaptureRegisters() / 2;
+
+ bool has_named_captures = false;
+ Handle<FixedArray> capture_map;
+ if (m > 1) {
+ // The existence of capture groups implies IRREGEXP kind.
+ DCHECK_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
+
+ Object* maybe_capture_map = regexp->CaptureNameMap();
+ if (maybe_capture_map->IsFixedArray()) {
+ has_named_captures = true;
+ capture_map = handle(FixedArray::cast(maybe_capture_map));
+ }
}
- if (species->IsConstructor()) return species;
+ DCHECK_IMPLIES(has_named_captures, FLAG_harmony_regexp_named_captures);
+ const int argc = has_named_captures ? m + 3 : m + 2;
+ ScopedVector<Handle<Object>> argv(argc);
- THROW_NEW_ERROR(
- isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
+ int cursor = 0;
+ for (int j = 0; j < m; j++) {
+ bool ok;
+ Handle<String> capture =
+ RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
+ if (ok) {
+ argv[cursor++] = capture;
+ } else {
+ argv[cursor++] = factory->undefined_value();
+ }
+ }
+
+ argv[cursor++] = handle(Smi::FromInt(index), isolate);
+ argv[cursor++] = subject;
+
+ if (has_named_captures) {
+ argv[cursor++] = ConstructNamedCaptureGroupsObject(
+ isolate, capture_map, [&argv](int ix) { return *argv[ix]; });
+ }
+
+ DCHECK_EQ(cursor, argc);
+
+ Handle<Object> replacement_obj;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, replacement_obj,
+ Execution::Call(isolate, replace_obj, factory->undefined_value(), argc,
+ argv.start()));
+
+ Handle<String> replacement;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, replacement, Object::ToString(isolate, replacement_obj));
+
+ builder.AppendString(replacement);
+ builder.AppendString(
+ factory->NewSubString(subject, end_of_match, subject->length()));
+
+ RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
}
+namespace {
+
MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate,
Handle<Object> object,
uint32_t* out) {
@@ -1384,7 +1607,7 @@ RUNTIME_FUNCTION(Runtime_RegExpSplit) {
Handle<JSFunction> regexp_fun = isolate->regexp_function();
Handle<Object> ctor;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, ctor, SpeciesConstructor(isolate, recv, regexp_fun));
+ isolate, ctor, Object::SpeciesConstructor(isolate, recv, regexp_fun));
Handle<Object> flags_obj;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
@@ -1627,14 +1850,14 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
isolate, position_obj,
Object::GetProperty(result, factory->index_string()));
- // TODO(jgruber): Extract and correct error handling. Since we can go up to
- // 2^53 - 1 (at least for ToLength), we might actually need uint64_t here?
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, position_obj, Object::ToInteger(isolate, position_obj));
const uint32_t position =
std::min(PositiveNumberToUint32(*position_obj), length);
+ // Do not reserve capacity since captures_length is user-controlled.
ZoneVector<Handle<Object>> captures(&zone);
+
for (int n = 0; n < captures_length; n++) {
Handle<Object> capture;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
@@ -1647,17 +1870,32 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
captures.push_back(capture);
}
+ Handle<Object> groups_obj = isolate->factory()->undefined_value();
+ if (FLAG_harmony_regexp_named_captures) {
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, groups_obj,
+ Object::GetProperty(result, factory->groups_string()));
+ }
+
+ const bool has_named_captures = !groups_obj->IsUndefined(isolate);
+ DCHECK_IMPLIES(has_named_captures, FLAG_harmony_regexp_named_captures);
+
Handle<String> replacement;
if (functional_replace) {
- const int argc = captures_length + 2;
+ const int argc =
+ has_named_captures ? captures_length + 3 : captures_length + 2;
ScopedVector<Handle<Object>> argv(argc);
+ int cursor = 0;
for (int j = 0; j < captures_length; j++) {
- argv[j] = captures[j];
+ argv[cursor++] = captures[j];
}
- argv[captures_length] = handle(Smi::FromInt(position), isolate);
- argv[captures_length + 1] = string;
+ argv[cursor++] = handle(Smi::FromInt(position), isolate);
+ argv[cursor++] = string;
+ if (has_named_captures) argv[cursor++] = groups_obj;
+
+ DCHECK_EQ(cursor, argc);
Handle<Object> replacement_obj;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
@@ -1668,7 +1906,13 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, replacement, Object::ToString(isolate, replacement_obj));
} else {
- VectorBackedMatch m(isolate, string, match, position, &captures);
+ DCHECK(!functional_replace);
+ if (!groups_obj->IsUndefined(isolate)) {
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, groups_obj, JSReceiver::ToObject(isolate, groups_obj));
+ }
+ VectorBackedMatch m(isolate, string, match, position, &captures,
+ groups_obj);
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, replacement, String::GetSubstitution(isolate, &m, replace));
}
@@ -1692,7 +1936,7 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
RUNTIME_FUNCTION(Runtime_RegExpExecReThrow) {
SealHandleScope shs(isolate);
- DCHECK_EQ(4, args.length());
+ DCHECK_EQ(0, args.length());
Object* exception = isolate->pending_exception();
isolate->clear_pending_exception();
return isolate->ReThrow(exception);
diff --git a/chromium/v8/src/runtime/runtime-strings.cc b/chromium/v8/src/runtime/runtime-strings.cc
index 3a435913e35..1ef04ed467f 100644
--- a/chromium/v8/src/runtime/runtime-strings.cc
+++ b/chromium/v8/src/runtime/runtime-strings.cc
@@ -31,13 +31,21 @@ RUNTIME_FUNCTION(Runtime_GetSubstitution) {
: match_(match), prefix_(prefix), suffix_(suffix) {}
Handle<String> GetMatch() override { return match_; }
+ Handle<String> GetPrefix() override { return prefix_; }
+ Handle<String> GetSuffix() override { return suffix_; }
+
+ int CaptureCount() override { return 0; }
+ bool HasNamedCaptures() override { return false; }
MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
*capture_exists = false;
return match_; // Return arbitrary string handle.
}
- Handle<String> GetPrefix() override { return prefix_; }
- Handle<String> GetSuffix() override { return suffix_; }
- int CaptureCount() override { return 0; }
+ MaybeHandle<String> GetNamedCapture(Handle<String> name,
+ CaptureState* state) override {
+ UNREACHABLE();
+ *state = INVALID;
+ return MaybeHandle<String>();
+ }
private:
Handle<String> match_, prefix_, suffix_;
@@ -191,15 +199,9 @@ RUNTIME_FUNCTION(Runtime_SubString) {
RUNTIME_FUNCTION(Runtime_StringAdd) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
- CONVERT_ARG_HANDLE_CHECKED(Object, obj1, 0);
- CONVERT_ARG_HANDLE_CHECKED(Object, obj2, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
isolate->counters()->string_add_runtime()->Increment();
- MaybeHandle<String> maybe_str1(Object::ToString(isolate, obj1));
- MaybeHandle<String> maybe_str2(Object::ToString(isolate, obj2));
- Handle<String> str1;
- Handle<String> str2;
- maybe_str1.ToHandle(&str1);
- maybe_str2.ToHandle(&str2);
RETURN_RESULT_OR_FAILURE(isolate,
isolate->factory()->NewConsString(str1, str2));
}
diff --git a/chromium/v8/src/runtime/runtime-test.cc b/chromium/v8/src/runtime/runtime-test.cc
index c6234fcd853..4574b5103e1 100644
--- a/chromium/v8/src/runtime/runtime-test.cc
+++ b/chromium/v8/src/runtime/runtime-test.cc
@@ -45,7 +45,7 @@ bool IsWasmCompileAllowed(v8::Isolate* isolate, v8::Local<v8::Value> value,
// Use the compile controls for instantiation, too
bool IsWasmInstantiateAllowed(v8::Isolate* isolate,
v8::Local<v8::Value> module_or_bytes,
- v8::MaybeLocal<v8::Value> ffi, bool is_async) {
+ bool is_async) {
DCHECK_GT(g_PerIsolateWasmControls.Get().count(isolate), 0);
const WasmCompileControls& ctrls = g_PerIsolateWasmControls.Get().at(isolate);
if (is_async && ctrls.AllowAnySizeForAsync) return true;
@@ -57,6 +57,60 @@ bool IsWasmInstantiateAllowed(v8::Isolate* isolate,
return static_cast<uint32_t>(module->GetWasmWireBytes()->Length()) <=
ctrls.MaxWasmBufferSize;
}
+
+v8::Local<v8::Value> NewRangeException(v8::Isolate* isolate,
+ const char* message) {
+ return v8::Exception::RangeError(
+ v8::String::NewFromOneByte(isolate,
+ reinterpret_cast<const uint8_t*>(message),
+ v8::NewStringType::kNormal)
+ .ToLocalChecked());
+}
+
+void ThrowRangeException(v8::Isolate* isolate, const char* message) {
+ isolate->ThrowException(NewRangeException(isolate, message));
+}
+
+void RejectPromiseWithRangeError(
+ const v8::FunctionCallbackInfo<v8::Value>& args, const char* message) {
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ v8::Local<v8::Promise::Resolver> resolver;
+ if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
+ v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
+ return_value.Set(resolver->GetPromise());
+
+ auto maybe = resolver->Reject(context, NewRangeException(isolate, message));
+ CHECK(!maybe.IsNothing());
+ return;
+}
+
+bool WasmModuleOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (IsWasmCompileAllowed(args.GetIsolate(), args[0], false)) return false;
+ ThrowRangeException(args.GetIsolate(), "Sync compile not allowed");
+ return true;
+}
+
+bool WasmCompileOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (IsWasmCompileAllowed(args.GetIsolate(), args[0], true)) return false;
+ RejectPromiseWithRangeError(args, "Async compile not allowed");
+ return true;
+}
+
+bool WasmInstanceOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (IsWasmInstantiateAllowed(args.GetIsolate(), args[0], false)) return false;
+ ThrowRangeException(args.GetIsolate(), "Sync instantiate not allowed");
+ return true;
+}
+
+bool WasmInstantiateOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (IsWasmInstantiateAllowed(args.GetIsolate(), args[0], true)) return false;
+ RejectPromiseWithRangeError(args, "Async instantiate not allowed");
+ return true;
+}
+
} // namespace
namespace v8 {
@@ -71,6 +125,20 @@ RUNTIME_FUNCTION(Runtime_ConstructDouble) {
return *isolate->factory()->NewNumber(uint64_to_double(result));
}
+RUNTIME_FUNCTION(Runtime_ConstructConsString) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(2, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(String, left, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, right, 1);
+
+ CHECK(left->IsOneByteRepresentation());
+ CHECK(right->IsOneByteRepresentation());
+
+ const bool kIsOneByte = true;
+ const int length = left->length() + right->length();
+ return *isolate->factory()->NewConsString(left, right, length, kIsOneByte);
+}
+
RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
@@ -142,6 +210,25 @@ RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
isolate->concurrent_recompilation_enabled());
}
+RUNTIME_FUNCTION(Runtime_TypeProfile) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+
+ if (!FLAG_type_profile) {
+ return isolate->heap()->undefined_value();
+ }
+
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ if (function->has_feedback_vector()) {
+ FeedbackVector* vector = function->feedback_vector();
+ if (vector->metadata()->HasTypeProfileSlot()) {
+ FeedbackSlot slot = vector->GetTypeProfileSlot();
+ CollectTypeProfileNexus nexus(vector, slot);
+ return nexus.GetTypeProfile();
+ }
+ }
+ return *isolate->factory()->NewJSObject(isolate->object_function());
+}
RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
HandleScope scope(isolate);
@@ -178,8 +265,7 @@ RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
function->MarkForOptimization();
- Code* unoptimized = function->shared()->code();
- if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
+ if (args.length() == 2) {
CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
isolate->concurrent_recompilation_enabled()) {
@@ -190,53 +276,6 @@ RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(Runtime_InterpretFunctionOnNextCall) {
- HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
- if (!function_object->IsJSFunction()) {
- return isolate->heap()->undefined_value();
- }
- Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
-
- // Do not tier down if we are already on optimized code. Replacing optimized
- // code without actual deoptimization can lead to funny bugs.
- if (function->code()->kind() != Code::OPTIMIZED_FUNCTION &&
- function->shared()->HasBytecodeArray()) {
- function->ReplaceCode(*isolate->builtins()->InterpreterEntryTrampoline());
- }
- return isolate->heap()->undefined_value();
-}
-
-RUNTIME_FUNCTION(Runtime_BaselineFunctionOnNextCall) {
- HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
- if (!function_object->IsJSFunction()) {
- return isolate->heap()->undefined_value();
- }
- Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
-
- // If function isn't compiled, compile it now.
- if (!function->shared()->is_compiled() &&
- !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) {
- return isolate->heap()->undefined_value();
- }
-
- // Do not tier down if we are already on optimized code. Replacing optimized
- // code without actual deoptimization can lead to funny bugs.
- if (function->code()->kind() != Code::OPTIMIZED_FUNCTION &&
- function->code()->kind() != Code::FUNCTION) {
- if (function->shared()->HasBaselineCode()) {
- function->ReplaceCode(function->shared()->code());
- } else {
- function->MarkForBaseline();
- }
- }
-
- return isolate->heap()->undefined_value();
-}
-
RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
HandleScope scope(isolate);
DCHECK(args.length() == 0 || args.length() == 1);
@@ -346,6 +385,13 @@ RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
return Smi::FromInt(function->shared()->opt_count());
}
+RUNTIME_FUNCTION(Runtime_GetDeoptCount) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ return Smi::FromInt(function->shared()->deopt_count());
+}
+
static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
args.GetReturnValue().Set(args.This());
}
@@ -478,14 +524,17 @@ RUNTIME_FUNCTION(Runtime_SetWasmCompileControls) {
WasmCompileControls& ctrl = (*g_PerIsolateWasmControls.Pointer())[v8_isolate];
ctrl.AllowAnySizeForAsync = allow_async;
ctrl.MaxWasmBufferSize = static_cast<uint32_t>(block_size->value());
- isolate->set_allow_wasm_compile_callback(IsWasmCompileAllowed);
+ v8_isolate->SetWasmModuleCallback(WasmModuleOverride);
+ v8_isolate->SetWasmCompileCallback(WasmCompileOverride);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls) {
HandleScope scope(isolate);
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
CHECK(args.length() == 0);
- isolate->set_allow_wasm_instantiate_callback(IsWasmInstantiateAllowed);
+ v8_isolate->SetWasmInstanceCallback(WasmInstanceOverride);
+ v8_isolate->SetWasmInstantiateCallback(WasmInstantiateOverride);
return isolate->heap()->undefined_value();
}
@@ -528,6 +577,7 @@ RUNTIME_FUNCTION(Runtime_DebugPrint) {
if (args[0]->IsString() && isolate->context() != nullptr) {
// If we have a string, assume it's a code "marker"
// and print some interesting cpu debugging info.
+ args[0]->Print(os);
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
os << "fp = " << static_cast<void*>(frame->fp())
@@ -535,8 +585,8 @@ RUNTIME_FUNCTION(Runtime_DebugPrint) {
<< ", caller_sp = " << static_cast<void*>(frame->caller_sp()) << ": ";
} else {
os << "DebugPrint: ";
+ args[0]->Print(os);
}
- args[0]->Print(os);
if (args[0]->IsHeapObject()) {
HeapObject::cast(args[0])->map()->Print(os);
}
@@ -904,7 +954,7 @@ RUNTIME_FUNCTION(Runtime_ValidateWasmOrphanedInstance) {
return isolate->heap()->ToBoolean(true);
}
-RUNTIME_FUNCTION(Runtime_Verify) {
+RUNTIME_FUNCTION(Runtime_HeapObjectVerify) {
HandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
@@ -921,5 +971,41 @@ RUNTIME_FUNCTION(Runtime_Verify) {
return isolate->heap()->ToBoolean(true);
}
+RUNTIME_FUNCTION(Runtime_WasmNumInterpretedCalls) {
+ DCHECK_EQ(1, args.length());
+ HandleScope scope(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
+ CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
+ Handle<WasmInstanceObject> instance =
+ Handle<WasmInstanceObject>::cast(instance_obj);
+ if (!instance->has_debug_info()) return 0;
+ uint64_t num = instance->debug_info()->NumInterpretedCalls();
+ return *isolate->factory()->NewNumberFromSize(static_cast<size_t>(num));
+}
+
+RUNTIME_FUNCTION(Runtime_RedirectToWasmInterpreter) {
+ DCHECK_EQ(2, args.length());
+ HandleScope scope(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
+ CONVERT_SMI_ARG_CHECKED(function_index, 1);
+ CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
+ Handle<WasmInstanceObject> instance =
+ Handle<WasmInstanceObject>::cast(instance_obj);
+ Handle<WasmDebugInfo> debug_info =
+ WasmInstanceObject::GetOrCreateDebugInfo(instance);
+ WasmDebugInfo::RedirectToInterpreter(debug_info,
+ Vector<int>(&function_index, 1));
+ return isolate->heap()->undefined_value();
+}
+
+RUNTIME_FUNCTION(Runtime_IncrementWaitCount) {
+ isolate->IncrementWaitCountForTesting();
+ return isolate->heap()->undefined_value();
+}
+
+RUNTIME_FUNCTION(Runtime_DecrementWaitCount) {
+ isolate->DecrementWaitCountForTesting();
+ return isolate->heap()->undefined_value();
+}
} // namespace internal
} // namespace v8
diff --git a/chromium/v8/src/runtime/runtime-typedarray.cc b/chromium/v8/src/runtime/runtime-typedarray.cc
index 4ca7bbb009f..eeaa40e5ea6 100644
--- a/chromium/v8/src/runtime/runtime-typedarray.cc
+++ b/chromium/v8/src/runtime/runtime-typedarray.cc
@@ -5,6 +5,7 @@
#include "src/runtime/runtime-utils.h"
#include "src/arguments.h"
+#include "src/elements.h"
#include "src/factory.h"
#include "src/messages.h"
#include "src/objects-inl.h"
@@ -21,43 +22,18 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
}
-RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
HandleScope scope(isolate);
- DCHECK_EQ(4, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
- CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
-
- if (source->was_neutered() || target->was_neutered()) {
+ DCHECK_EQ(1, args.length());
+ Handle<Object> argument = args.at(0);
+ // This runtime function is exposed in ClusterFuzz and as such has to
+ // support arbitrary arguments.
+ if (!argument->IsJSArrayBuffer()) {
THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewTypeError(MessageTemplate::kDetachedOperation,
- isolate->factory()->NewStringFromAsciiChecked(
- "ArrayBuffer.prototype.slice")));
+ isolate, NewTypeError(MessageTemplate::kNotTypedArray));
}
+ Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(argument);
- CHECK(!source.is_identical_to(target));
- size_t start = 0, target_length = 0;
- CHECK(TryNumberToSize(*first, &start));
- CHECK(TryNumberToSize(*new_length, &target_length));
- CHECK(NumberToSize(target->byte_length()) >= target_length);
-
- if (target_length == 0) return isolate->heap()->undefined_value();
-
- size_t source_byte_length = NumberToSize(source->byte_length());
- CHECK(start <= source_byte_length);
- CHECK(source_byte_length - start >= target_length);
- uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
- uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
- CopyBytes(target_data, source_data + start, target_length);
- return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
- HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
if (array_buffer->backing_store() == NULL) {
CHECK(Smi::kZero == array_buffer->byte_length());
return isolate->heap()->undefined_value();
@@ -74,203 +50,6 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
return isolate->heap()->undefined_value();
}
-
-void Runtime::ArrayIdToTypeAndSize(int arrayId, ExternalArrayType* array_type,
- 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; \
- *fixed_elements_kind = TYPE##_ELEMENTS; \
- *element_size = size; \
- break;
-
- TYPED_ARRAYS(ARRAY_ID_CASE)
-#undef ARRAY_ID_CASE
-
- default:
- UNREACHABLE();
- }
-}
-
-
-RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
- HandleScope scope(isolate);
- DCHECK_EQ(6, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
- CONVERT_SMI_ARG_CHECKED(arrayId, 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
- CONVERT_BOOLEAN_ARG_CHECKED(initialize, 5);
-
- CHECK(arrayId >= Runtime::ARRAY_ID_FIRST &&
- arrayId <= Runtime::ARRAY_ID_LAST);
-
- ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
- size_t element_size = 1; // Bogus initialization.
- ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
- Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind,
- &element_size);
- CHECK(holder->map()->elements_kind() == fixed_elements_kind);
-
- size_t byte_offset = 0;
- size_t byte_length = 0;
- CHECK(TryNumberToSize(*byte_offset_object, &byte_offset));
- CHECK(TryNumberToSize(*byte_length_object, &byte_length));
-
- if (maybe_buffer->IsJSArrayBuffer()) {
- Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
- size_t array_buffer_byte_length = NumberToSize(buffer->byte_length());
- CHECK(byte_offset <= array_buffer_byte_length);
- CHECK(array_buffer_byte_length - byte_offset >= byte_length);
- } else {
- CHECK(maybe_buffer->IsNull(isolate));
- }
-
- CHECK(byte_length % element_size == 0);
- size_t length = byte_length / element_size;
-
- if (length > static_cast<unsigned>(Smi::kMaxValue)) {
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayLength));
- }
-
- // All checks are done, now we can modify objects.
-
- DCHECK_EQ(v8::ArrayBufferView::kInternalFieldCount,
- holder->GetInternalFieldCount());
- for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
- holder->SetInternalField(i, Smi::kZero);
- }
- Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
- holder->set_length(*length_obj);
- holder->set_byte_offset(*byte_offset_object);
- holder->set_byte_length(*byte_length_object);
-
- if (!maybe_buffer->IsNull(isolate)) {
- Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
- holder->set_buffer(*buffer);
-
- 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();
- JSArrayBuffer::Setup(buffer, isolate, true, NULL, byte_length,
- SharedFlag::kNotShared);
- holder->set_buffer(*buffer);
- Handle<FixedTypedArrayBase> elements =
- isolate->factory()->NewFixedTypedArray(static_cast<int>(length),
- array_type, initialize);
- holder->set_elements(*elements);
- }
- return isolate->heap()->undefined_value();
-}
-
-
-// Initializes a typed array from an array-like object.
-// If an array-like object happens to be a typed array of the same type,
-// initializes backing store using memove.
-//
-// Returns true if backing store was initialized or false otherwise.
-RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
- HandleScope scope(isolate);
- DCHECK_EQ(4, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
- CONVERT_SMI_ARG_CHECKED(arrayId, 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
- CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 3);
-
- CHECK(arrayId >= Runtime::ARRAY_ID_FIRST &&
- arrayId <= Runtime::ARRAY_ID_LAST);
-
- ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
- size_t element_size = 1; // Bogus initialization.
- ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
- Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind,
- &element_size);
-
- CHECK(holder->map()->elements_kind() == fixed_elements_kind);
-
- Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
- size_t length = 0;
- if (source->IsJSTypedArray() &&
- JSTypedArray::cast(*source)->type() == array_type) {
- length = JSTypedArray::cast(*source)->length_value();
- } else {
- CHECK(TryNumberToSize(*length_obj, &length));
- }
-
- if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
- (length > (kMaxInt / element_size))) {
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayLength));
- }
- size_t byte_length = length * element_size;
-
- DCHECK_EQ(v8::ArrayBufferView::kInternalFieldCount,
- holder->GetInternalFieldCount());
- for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
- holder->SetInternalField(i, Smi::kZero);
- }
-
- // NOTE: not initializing backing store.
- // We assume that the caller of this function will initialize holder
- // with the loop
- // for(i = 0; i < length; i++) { holder[i] = source[i]; }
- // We assume that the caller of this function is always a typed array
- // constructor.
- // If source is a typed array, this loop will always run to completion,
- // so we are sure that the backing store will be initialized.
- // Otherwise, the indexing operation might throw, so the loop will not
- // run to completion and the typed array might remain partly initialized.
- // However we further assume that the caller of this function is a typed array
- // constructor, and the exception will propagate out of the constructor,
- // therefore uninitialized memory will not be accessible by a user program.
- //
- // TODO(dslomov): revise this once we support subclassing.
-
- if (!JSArrayBuffer::SetupAllocatingData(buffer, isolate, byte_length,
- false)) {
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
- }
-
- holder->set_buffer(*buffer);
- holder->set_byte_offset(Smi::kZero);
- Handle<Object> byte_length_obj(
- isolate->factory()->NewNumberFromSize(byte_length));
- holder->set_byte_length(*byte_length_obj);
- length_obj = isolate->factory()->NewNumberFromSize(length);
- holder->set_length(*length_obj);
-
- 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));
-
- if (typed_array->type() == holder->type()) {
- uint8_t* backing_store =
- static_cast<uint8_t*>(typed_array->GetBuffer()->backing_store());
- size_t source_byte_offset = NumberToSize(typed_array->byte_offset());
- memcpy(buffer->backing_store(), backing_store + source_byte_offset,
- byte_length);
- return isolate->heap()->true_value();
- }
- }
-
- return isolate->heap()->false_value();
-}
-
-
#define BUFFER_VIEW_GETTER(Type, getter, accessor) \
RUNTIME_FUNCTION(Runtime_##Type##Get##getter) { \
HandleScope scope(isolate); \
@@ -316,8 +95,9 @@ RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
isolate, NewTypeError(MessageTemplate::kNotTypedArray));
}
- if (!args[1]->IsJSTypedArray())
+ if (!args[1]->IsJSTypedArray()) {
return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
+ }
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1);
diff --git a/chromium/v8/src/runtime/runtime-wasm.cc b/chromium/v8/src/runtime/runtime-wasm.cc
index 9f125c1345e..090d5b4a40e 100644
--- a/chromium/v8/src/runtime/runtime-wasm.cc
+++ b/chromium/v8/src/runtime/runtime-wasm.cc
@@ -12,6 +12,8 @@
#include "src/factory.h"
#include "src/frames-inl.h"
#include "src/objects-inl.h"
+#include "src/objects/frame-array-inl.h"
+#include "src/trap-handler/trap-handler.h"
#include "src/v8memory.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
@@ -43,10 +45,8 @@ RUNTIME_FUNCTION(Runtime_WasmMemorySize) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
- Handle<WasmInstanceObject> instance(GetWasmInstanceOnStackTop(isolate),
- isolate);
- return *isolate->factory()->NewNumberFromInt(
- wasm::GetInstanceMemorySize(isolate, instance));
+ int32_t mem_size = GetWasmInstanceOnStackTop(isolate)->GetMemorySize();
+ return *isolate->factory()->NewNumberFromInt(mem_size);
}
RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
@@ -61,7 +61,7 @@ RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
isolate->set_context(instance->compiled_module()->ptr_to_native_context());
return *isolate->factory()->NewNumberFromInt(
- wasm::GrowMemory(isolate, instance, delta_pages));
+ WasmInstanceObject::GrowMemory(isolate, instance, delta_pages));
}
Object* ThrowRuntimeError(Isolate* isolate, int message_id, int byte_offset,
@@ -103,19 +103,10 @@ Object* ThrowRuntimeError(Isolate* isolate, int message_id, int byte_offset,
Handle<FixedArray> stack_elements(
FixedArray::cast(JSArray::cast(*detailed_stack_trace_obj)->elements()));
DCHECK_GE(stack_elements->length(), 1);
- Handle<JSObject> top_frame(JSObject::cast(stack_elements->get(0)));
- Handle<String> wasm_offset_key =
- isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("column"));
- LookupIterator it(top_frame, wasm_offset_key, top_frame,
- LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
- if (it.IsFound()) {
- DCHECK(JSReceiver::GetDataProperty(&it)->IsSmi());
- // Make column number 1-based here.
- Maybe<bool> data_set = JSReceiver::SetDataProperty(
- &it, handle(Smi::FromInt(byte_offset + 1), isolate));
- DCHECK(data_set.IsJust() && data_set.FromJust() == true);
- USE(data_set);
+ Handle<StackFrameInfo> top_frame(
+ StackFrameInfo::cast(stack_elements->get(0)));
+ if (top_frame->column_number()) {
+ top_frame->set_column_number(byte_offset + 1);
}
}
@@ -135,6 +126,14 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
return ThrowRuntimeError(isolate, message_id, byte_offset, true);
}
+RUNTIME_FUNCTION(Runtime_ThrowWasmStackOverflow) {
+ SealHandleScope shs(isolate);
+ DCHECK_LE(0, args.length());
+ DCHECK_NULL(isolate->context());
+ isolate->set_context(GetWasmContextOnStackTop(isolate));
+ return isolate->StackOverflow();
+}
+
RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
@@ -168,6 +167,16 @@ RUNTIME_FUNCTION(Runtime_WasmGetCaughtExceptionValue) {
return exception;
}
+RUNTIME_FUNCTION(Runtime_SetThreadInWasm) {
+ trap_handler::SetThreadInWasm();
+ return isolate->heap()->undefined_value();
+}
+
+RUNTIME_FUNCTION(Runtime_ClearThreadInWasm) {
+ trap_handler::ClearThreadInWasm();
+ return isolate->heap()->undefined_value();
+}
+
RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
DCHECK_EQ(3, args.length());
HandleScope scope(isolate);
@@ -189,13 +198,38 @@ RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
DCHECK_NULL(isolate->context());
isolate->set_context(instance->compiled_module()->ptr_to_native_context());
- instance->debug_info()->RunInterpreter(func_index, arg_buffer);
+ // Find the frame pointer of the interpreter entry.
+ Address frame_pointer = 0;
+ {
+ StackFrameIterator it(isolate, isolate->thread_local_top());
+ // On top: C entry stub.
+ DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
+ it.Advance();
+ // Next: the wasm interpreter entry.
+ DCHECK_EQ(StackFrame::WASM_INTERPRETER_ENTRY, it.frame()->type());
+ frame_pointer = it.frame()->fp();
+ }
+
+ bool success = instance->debug_info()->RunInterpreter(frame_pointer,
+ func_index, arg_buffer);
+
+ if (!success) {
+ DCHECK(isolate->has_pending_exception());
+ return isolate->heap()->exception();
+ }
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_WasmStackGuard) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
+ DCHECK(!trap_handler::UseTrapHandler() || trap_handler::IsThreadInWasm());
+
+ struct ClearAndRestoreThreadInWasm {
+ ClearAndRestoreThreadInWasm() { trap_handler::ClearThreadInWasm(); }
+
+ ~ClearAndRestoreThreadInWasm() { trap_handler::SetThreadInWasm(); }
+ } restore_thread_in_wasm;
// Set the current isolate's context.
DCHECK_NULL(isolate->context());
@@ -208,5 +242,12 @@ RUNTIME_FUNCTION(Runtime_WasmStackGuard) {
return isolate->stack_guard()->HandleInterrupts();
}
+RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
+ DCHECK(args.length() == 0);
+ HandleScope scope(isolate);
+
+ return *wasm::CompileLazy(isolate);
+}
+
} // namespace internal
} // namespace v8
diff --git a/chromium/v8/src/runtime/runtime.h b/chromium/v8/src/runtime/runtime.h
index 6c5a039d672..eb5f09db9b9 100644
--- a/chromium/v8/src/runtime/runtime.h
+++ b/chromium/v8/src/runtime/runtime.h
@@ -37,7 +37,6 @@ namespace internal {
// are specified by inline comments
#define FOR_EACH_INTRINSIC_ARRAY(F) \
- F(FinishArrayPrototypeSetup, 1, 1) \
F(SpecialArrayFunctions, 0, 1) \
F(TransitionElementsKind, 2, 1) \
F(RemoveArrayHoles, 2, 1) \
@@ -63,16 +62,13 @@ namespace internal {
F(ThrowNotIntegerSharedTypedArrayError, 1, 1) \
F(ThrowNotInt32SharedTypedArrayError, 1, 1) \
F(ThrowInvalidAtomicAccessIndexError, 0, 1) \
+ F(AtomicsExchange, 3, 1) \
F(AtomicsCompareExchange, 4, 1) \
F(AtomicsAdd, 3, 1) \
F(AtomicsSub, 3, 1) \
F(AtomicsAnd, 3, 1) \
F(AtomicsOr, 3, 1) \
F(AtomicsXor, 3, 1) \
- F(AtomicsExchange, 3, 1) \
- F(AtomicsIsLockFree, 1, 1) \
- F(AtomicsWait, 4, 1) \
- F(AtomicsWake, 3, 1) \
F(AtomicsNumWaitersForTesting, 2, 1) \
F(SetAllowAtomicsWait, 1, 1)
@@ -81,6 +77,7 @@ namespace internal {
F(ThrowConstructorNonCallableError, 1, 1) \
F(ThrowStaticPrototypeError, 0, 1) \
F(ThrowSuperAlreadyCalledError, 0, 1) \
+ F(ThrowSuperNotCalled, 0, 1) \
F(ThrowNotSuperConstructor, 2, 1) \
F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 4, 1) \
@@ -125,7 +122,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_COMPILER(F) \
F(CompileLazy, 1, 1) \
- F(CompileBaseline, 1, 1) \
F(CompileOptimized_Concurrent, 1, 1) \
F(CompileOptimized_NotConcurrent, 1, 1) \
F(NotifyStubFailure, 0, 1) \
@@ -241,15 +237,18 @@ namespace internal {
F(IsFunction, 1, 1) \
F(FunctionToString, 1, 1)
-#define FOR_EACH_INTRINSIC_GENERATOR(F) \
- F(CreateJSGeneratorObject, 2, 1) \
- F(GeneratorClose, 1, 1) \
- F(GeneratorGetFunction, 1, 1) \
- F(GeneratorGetReceiver, 1, 1) \
- F(GeneratorGetContext, 1, 1) \
- F(GeneratorGetInputOrDebugPos, 1, 1) \
- F(GeneratorGetContinuation, 1, 1) \
- F(GeneratorGetSourcePosition, 1, 1) \
+#define FOR_EACH_INTRINSIC_GENERATOR(F) \
+ F(CreateJSGeneratorObject, 2, 1) \
+ F(GeneratorClose, 1, 1) \
+ F(GeneratorGetFunction, 1, 1) \
+ F(GeneratorGetReceiver, 1, 1) \
+ F(GeneratorGetContext, 1, 1) \
+ F(GeneratorGetInputOrDebugPos, 1, 1) \
+ F(AsyncGeneratorGetAwaitInputOrDebugPos, 1, 1) \
+ F(AsyncGeneratorResolve, 3, 1) \
+ F(AsyncGeneratorReject, 2, 1) \
+ F(GeneratorGetContinuation, 1, 1) \
+ F(GeneratorGetSourcePosition, 1, 1) \
F(GeneratorGetResumeMode, 1, 1)
#ifdef V8_I18N_SUPPORT
@@ -266,9 +265,9 @@ namespace internal {
F(InternalDateFormatToParts, 2, 1) \
F(CreateNumberFormat, 3, 1) \
F(InternalNumberFormat, 2, 1) \
+ F(CurrencyDigits, 1, 1) \
F(CreateCollator, 3, 1) \
F(InternalCompare, 3, 1) \
- F(StringNormalize, 2, 1) \
F(CreateBreakIterator, 3, 1) \
F(BreakIteratorAdoptText, 2, 1) \
F(BreakIteratorFirst, 1, 1) \
@@ -317,12 +316,14 @@ namespace internal {
F(ThrowIncompatibleMethodReceiver, 2, 1) \
F(ThrowInvalidHint, 1, 1) \
F(ThrowInvalidStringLength, 0, 1) \
+ F(ThrowInvalidTypedArrayAlignment, 2, 1) \
F(ThrowIteratorResultNotAnObject, 1, 1) \
F(ThrowSymbolIteratorInvalid, 0, 1) \
F(ThrowNonCallableInInstanceOfCheck, 0, 1) \
F(ThrowNonObjectInInstanceOfCheck, 0, 1) \
F(ThrowNotConstructor, 1, 1) \
F(ThrowNotGeneric, 1, 1) \
+ F(ThrowRangeError, -1 /* >= 1 */, 1) \
F(ThrowReferenceError, 1, 1) \
F(ThrowStackOverflow, 0, 1) \
F(ThrowSymbolAsyncIteratorInvalid, 0, 1) \
@@ -355,7 +356,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_MATHS(F) F(GenerateRandomNumbers, 0, 1)
#define FOR_EACH_INTRINSIC_MODULE(F) \
- F(DynamicImportCall, 1, 1) \
+ F(DynamicImportCall, 2, 1) \
F(GetModuleNamespace, 1, 1) \
F(LoadModuleVariable, 1, 1) \
F(StoreModuleVariable, 2, 1)
@@ -371,11 +372,11 @@ namespace internal {
F(SmiLexicographicCompare, 2, 1) \
F(MaxSmi, 0, 1) \
F(IsSmi, 1, 1) \
- F(GetRootNaN, 0, 1) \
F(GetHoleNaNUpper, 0, 1) \
F(GetHoleNaNLower, 0, 1)
#define FOR_EACH_INTRINSIC_OBJECT(F) \
+ F(AddDictionaryProperty, 3, 1) \
F(GetPrototype, 1, 1) \
F(ObjectHasOwnProperty, 2, 1) \
F(ObjectCreate, 2, 1) \
@@ -401,6 +402,7 @@ namespace internal {
F(IsJSGlobalProxy, 1, 1) \
F(DefineAccessorPropertyUnchecked, 5, 1) \
F(DefineDataPropertyInLiteral, 6, 1) \
+ F(CollectTypeProfile, 3, 1) \
F(GetDataProperty, 2, 1) \
F(GetConstructorName, 1, 1) \
F(HasFastPackedElements, 1, 1) \
@@ -426,7 +428,8 @@ namespace internal {
F(CreateIterResultObject, 2, 1) \
F(CreateKeyValueArray, 2, 1) \
F(IsAccessCheckNeeded, 1, 1) \
- F(CreateDataProperty, 3, 1)
+ F(CreateDataProperty, 3, 1) \
+ F(IterableToListCanBeElided, 1, 1)
#define FOR_EACH_INTRINSIC_OPERATORS(F) \
F(Multiply, 2, 1) \
@@ -463,7 +466,9 @@ namespace internal {
F(PromiseRevokeReject, 1, 1) \
F(PromiseResult, 1, 1) \
F(PromiseStatus, 1, 1) \
- F(ReportPromiseReject, 2, 1)
+ F(ReportPromiseReject, 2, 1) \
+ F(IncrementWaitCount, 0, 1) \
+ F(DecrementWaitCount, 0, 1)
#define FOR_EACH_INTRINSIC_PROXY(F) \
F(IsJSProxy, 1, 1) \
@@ -478,7 +483,7 @@ namespace internal {
F(RegExpCreate, 1, 1) \
F(RegExpExec, 4, 1) \
F(RegExpExecMultiple, 4, 1) \
- F(RegExpExecReThrow, 4, 1) \
+ F(RegExpExecReThrow, 0, 1) \
F(RegExpInitializeAndCompile, 3, 1) \
F(RegExpInternalReplace, 3, 1) \
F(RegExpReplace, 3, 1) \
@@ -548,18 +553,19 @@ namespace internal {
#define FOR_EACH_INTRINSIC_TEST(F) \
F(ConstructDouble, 2, 1) \
+ F(ConstructConsString, 2, 1) \
F(DeoptimizeFunction, 1, 1) \
F(DeoptimizeNow, 0, 1) \
F(RunningInSimulator, 0, 1) \
F(IsConcurrentRecompilationSupported, 0, 1) \
F(OptimizeFunctionOnNextCall, -1, 1) \
- F(InterpretFunctionOnNextCall, 1, 1) \
- F(BaselineFunctionOnNextCall, 1, 1) \
+ F(TypeProfile, 1, 1) \
F(OptimizeOsr, -1, 1) \
F(NeverOptimizeFunction, 1, 1) \
F(GetOptimizationStatus, -1, 1) \
F(UnblockConcurrentRecompilation, 0, 1) \
F(GetOptimizationCount, 1, 1) \
+ F(GetDeoptCount, 1, 1) \
F(GetUndetectable, 0, 1) \
F(GetCallable, 0, 1) \
F(ClearFunctionFeedback, 1, 1) \
@@ -611,14 +617,13 @@ namespace internal {
F(ValidateWasmOrphanedInstance, 1, 1) \
F(SetWasmCompileControls, 2, 1) \
F(SetWasmInstantiateControls, 0, 1) \
- F(Verify, 1, 1)
+ F(HeapObjectVerify, 1, 1) \
+ F(WasmNumInterpretedCalls, 1, 1) \
+ F(RedirectToWasmInterpreter, 2, 1)
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
F(ArrayBufferGetByteLength, 1, 1) \
- F(ArrayBufferSliceImpl, 4, 1) \
F(ArrayBufferNeuter, 1, 1) \
- F(TypedArrayInitialize, 6, 1) \
- F(TypedArrayInitializeFromArrayLike, 4, 1) \
F(ArrayBufferViewGetByteLength, 1, 1) \
F(ArrayBufferViewGetByteOffset, 1, 1) \
F(TypedArrayGetLength, 1, 1) \
@@ -636,11 +641,15 @@ namespace internal {
F(WasmMemorySize, 0, 1) \
F(ThrowWasmError, 2, 1) \
F(ThrowWasmErrorFromTrapIf, 1, 1) \
+ F(ThrowWasmStackOverflow, 0, 1) \
F(WasmThrowTypeError, 0, 1) \
F(WasmThrow, 2, 1) \
F(WasmGetCaughtExceptionValue, 1, 1) \
F(WasmRunInterpreter, 3, 1) \
- F(WasmStackGuard, 0, 1)
+ F(WasmStackGuard, 0, 1) \
+ F(SetThreadInWasm, 0, 1) \
+ F(ClearThreadInWasm, 0, 1) \
+ F(WasmCompileLazy, 0, 1)
#define FOR_EACH_INTRINSIC_RETURN_PAIR(F) \
F(LoadLookupSlotForCall, 1, 2)
@@ -663,7 +672,6 @@ namespace internal {
F(LoadGlobalIC_Slow, 3, 1) \
F(LoadIC_Miss, 4, 1) \
F(LoadPropertyWithInterceptor, 5, 1) \
- F(LoadPropertyWithInterceptorOnly, 3, 1) \
F(StoreCallbackProperty, 6, 1) \
F(StoreIC_Miss, 5, 1) \
F(StorePropertyWithInterceptor, 5, 1) \
@@ -777,27 +785,8 @@ class Runtime : public AllStatic {
Isolate* isolate, Handle<Object> object, Handle<Object> key,
bool* is_found_out = nullptr);
- enum TypedArrayId {
- // arrayIds below should be synchronized with typedarray.js natives.
- ARRAY_ID_UINT8 = 1,
- ARRAY_ID_INT8 = 2,
- ARRAY_ID_UINT16 = 3,
- ARRAY_ID_INT16 = 4,
- ARRAY_ID_UINT32 = 5,
- ARRAY_ID_INT32 = 6,
- ARRAY_ID_FLOAT32 = 7,
- ARRAY_ID_FLOAT64 = 8,
- ARRAY_ID_UINT8_CLAMPED = 9,
- ARRAY_ID_FIRST = ARRAY_ID_UINT8,
- ARRAY_ID_LAST = ARRAY_ID_UINT8_CLAMPED
- };
-
- static void ArrayIdToTypeAndSize(int array_id, ExternalArrayType* type,
- ElementsKind* fixed_elements_kind,
- size_t* element_size);
-
- static MaybeHandle<JSArray> GetInternalProperties(Isolate* isolate,
- Handle<Object>);
+ MUST_USE_RESULT static MaybeHandle<JSArray> GetInternalProperties(
+ Isolate* isolate, Handle<Object>);
};