summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-10-18 15:03:02 -0700
committerMichaël Zasso <targos@protonmail.com>2017-10-18 17:01:41 -0700
commit3d1b3df9486c0e7708065257f7311902f6b7b366 (patch)
treecb051bdeaead11e06dcd97725783e0f113afb1bf /deps/v8/src/objects
parente2cddbb8ccdb7b3c4a40c8acc630f68703bc77b5 (diff)
downloadandroid-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.tar.gz
android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.tar.bz2
android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.zip
deps: update V8 to 6.2.414.32
PR-URL: https://github.com/nodejs/node/pull/15362 Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/objects')
-rw-r--r--deps/v8/src/objects/arguments-inl.h4
-rw-r--r--deps/v8/src/objects/arguments.h20
-rw-r--r--deps/v8/src/objects/debug-objects-inl.h16
-rw-r--r--deps/v8/src/objects/debug-objects.cc62
-rw-r--r--deps/v8/src/objects/debug-objects.h25
-rw-r--r--deps/v8/src/objects/descriptor-array.h3
-rw-r--r--deps/v8/src/objects/dictionary.h16
-rw-r--r--deps/v8/src/objects/hash-table.h11
-rw-r--r--deps/v8/src/objects/intl-objects.cc336
-rw-r--r--deps/v8/src/objects/intl-objects.h38
-rw-r--r--deps/v8/src/objects/literal-objects.h2
-rw-r--r--deps/v8/src/objects/map.h28
-rw-r--r--deps/v8/src/objects/module-info.h133
-rw-r--r--deps/v8/src/objects/module-inl.h67
-rw-r--r--deps/v8/src/objects/module.cc873
-rw-r--r--deps/v8/src/objects/module.h329
-rw-r--r--deps/v8/src/objects/name-inl.h5
-rw-r--r--deps/v8/src/objects/name.h14
-rw-r--r--deps/v8/src/objects/object-macros-undef.h2
-rw-r--r--deps/v8/src/objects/object-macros.h40
-rw-r--r--deps/v8/src/objects/scope-info.cc40
-rw-r--r--deps/v8/src/objects/scope-info.h17
-rw-r--r--deps/v8/src/objects/shared-function-info-inl.h63
-rw-r--r--deps/v8/src/objects/shared-function-info.h142
-rw-r--r--deps/v8/src/objects/string-inl.h3
-rw-r--r--deps/v8/src/objects/string.h22
26 files changed, 1833 insertions, 478 deletions
diff --git a/deps/v8/src/objects/arguments-inl.h b/deps/v8/src/objects/arguments-inl.h
index 32f5359e4b..48ff8daec4 100644
--- a/deps/v8/src/objects/arguments-inl.h
+++ b/deps/v8/src/objects/arguments-inl.h
@@ -15,12 +15,8 @@ namespace internal {
CAST_ACCESSOR(AliasedArgumentsEntry)
CAST_ACCESSOR(JSArgumentsObject)
-CAST_ACCESSOR(JSSloppyArgumentsObject)
CAST_ACCESSOR(SloppyArgumentsElements)
-ACCESSORS(JSArgumentsObject, length, Object, kLengthOffset);
-ACCESSORS(JSSloppyArgumentsObject, callee, Object, kCalleeOffset);
-
SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
TYPE_CHECKER(JSArgumentsObject, JS_ARGUMENTS_TYPE)
diff --git a/deps/v8/src/objects/arguments.h b/deps/v8/src/objects/arguments.h
index 61c1a9cb41..64c34df993 100644
--- a/deps/v8/src/objects/arguments.h
+++ b/deps/v8/src/objects/arguments.h
@@ -14,16 +14,17 @@ namespace v8 {
namespace internal {
// Common superclass for JSSloppyArgumentsObject and JSStrictArgumentsObject.
+// Note that the instance type {JS_ARGUMENTS_TYPE} does _not_ guarantee the
+// below layout, the in-object properties might have transitioned to dictionary
+// mode already. Only use the below layout with the specific initial maps.
class JSArgumentsObject : public JSObject {
public:
// Offsets of object fields.
static const int kLengthOffset = JSObject::kHeaderSize;
- static const int kHeaderSize = kLengthOffset + kPointerSize;
+ static const int kSize = kLengthOffset + kPointerSize;
// Indices of in-object properties.
static const int kLengthIndex = 0;
- DECL_ACCESSORS(length, Object)
-
DECL_VERIFIER(JSArgumentsObject)
DECL_CAST(JSArgumentsObject)
@@ -36,16 +37,11 @@ class JSArgumentsObject : public JSObject {
class JSSloppyArgumentsObject : public JSArgumentsObject {
public:
// Offsets of object fields.
- static const int kCalleeOffset = JSArgumentsObject::kHeaderSize;
+ static const int kCalleeOffset = JSArgumentsObject::kSize;
static const int kSize = kCalleeOffset + kPointerSize;
// Indices of in-object properties.
static const int kCalleeIndex = kLengthIndex + 1;
- DECL_ACCESSORS(callee, Object)
-
- DECL_VERIFIER(JSSloppyArgumentsObject)
- DECL_CAST(JSSloppyArgumentsObject)
-
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSSloppyArgumentsObject);
};
@@ -55,9 +51,7 @@ class JSSloppyArgumentsObject : public JSArgumentsObject {
class JSStrictArgumentsObject : public JSArgumentsObject {
public:
// Offsets of object fields.
- static const int kSize = JSArgumentsObject::kHeaderSize;
-
- DECL_CAST(JSStrictArgumentsObject)
+ static const int kSize = JSArgumentsObject::kSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSStrictArgumentsObject);
@@ -100,7 +94,7 @@ class SloppyArgumentsElements : public FixedArray {
DECL_CAST(SloppyArgumentsElements)
#ifdef VERIFY_HEAP
- void SloppyArgumentsElementsVerify(JSSloppyArgumentsObject* holder);
+ void SloppyArgumentsElementsVerify(JSObject* holder);
#endif
private:
diff --git a/deps/v8/src/objects/debug-objects-inl.h b/deps/v8/src/objects/debug-objects-inl.h
index 1a117f15bd..002ac5215d 100644
--- a/deps/v8/src/objects/debug-objects-inl.h
+++ b/deps/v8/src/objects/debug-objects-inl.h
@@ -18,6 +18,7 @@ namespace internal {
CAST_ACCESSOR(BreakPointInfo)
CAST_ACCESSOR(DebugInfo)
CAST_ACCESSOR(CoverageInfo)
+CAST_ACCESSOR(BreakPoint)
SMI_ACCESSORS(DebugInfo, flags, kFlagsOffset)
ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
@@ -29,17 +30,13 @@ ACCESSORS(DebugInfo, coverage_info, Object, kCoverageInfoOffset)
SMI_ACCESSORS(BreakPointInfo, source_position, kSourcePositionOffset)
ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsOffset)
+SMI_ACCESSORS(BreakPoint, id, kIdOffset)
+ACCESSORS(BreakPoint, condition, String, kConditionOffset)
+
bool DebugInfo::HasDebugBytecodeArray() {
return debug_bytecode_array()->IsBytecodeArray();
}
-bool DebugInfo::HasDebugCode() {
- Code* code = shared()->code();
- bool has = code->kind() == Code::FUNCTION;
- DCHECK(!has || code->has_debug_break_slots());
- return has;
-}
-
BytecodeArray* DebugInfo::OriginalBytecodeArray() {
DCHECK(HasDebugBytecodeArray());
return shared()->bytecode_array();
@@ -50,11 +47,6 @@ BytecodeArray* DebugInfo::DebugBytecodeArray() {
return BytecodeArray::cast(debug_bytecode_array());
}
-Code* DebugInfo::DebugCode() {
- DCHECK(HasDebugCode());
- return shared()->code();
-}
-
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/objects/debug-objects.cc b/deps/v8/src/objects/debug-objects.cc
index f686c99639..59e9b20a09 100644
--- a/deps/v8/src/objects/debug-objects.cc
+++ b/deps/v8/src/objects/debug-objects.cc
@@ -12,13 +12,18 @@ bool DebugInfo::IsEmpty() const { return flags() == kNone; }
bool DebugInfo::HasBreakInfo() const { return (flags() & kHasBreakInfo) != 0; }
+bool DebugInfo::IsPreparedForBreakpoints() const {
+ DCHECK(HasBreakInfo());
+ return (flags() & kPreparedForBreakpoints) != 0;
+}
+
bool DebugInfo::ClearBreakInfo() {
Isolate* isolate = GetIsolate();
set_debug_bytecode_array(isolate->heap()->undefined_value());
set_break_points(isolate->heap()->empty_fixed_array());
- int new_flags = flags() & ~kHasBreakInfo;
+ int new_flags = flags() & ~kHasBreakInfo & ~kPreparedForBreakpoints;
set_flags(new_flags);
return new_flags == kNone;
@@ -171,16 +176,28 @@ bool DebugInfo::HasCoverageInfo() const {
bool DebugInfo::ClearCoverageInfo() {
DCHECK(FLAG_block_coverage);
- DCHECK(HasCoverageInfo());
- Isolate* isolate = GetIsolate();
+ if (HasCoverageInfo()) {
+ Isolate* isolate = GetIsolate();
- set_coverage_info(isolate->heap()->undefined_value());
+ set_coverage_info(isolate->heap()->undefined_value());
- int new_flags = flags() & ~kHasCoverageInfo;
- set_flags(new_flags);
+ int new_flags = flags() & ~kHasCoverageInfo;
+ set_flags(new_flags);
+ }
+ return flags() == kNone;
+}
- return new_flags == kNone;
+namespace {
+bool IsEqual(Object* break_point1, Object* break_point2) {
+ // TODO(kozyatinskiy): remove non-BreakPoint logic once the JS debug API has
+ // been removed.
+ if (break_point1->IsBreakPoint() != break_point2->IsBreakPoint())
+ return false;
+ if (!break_point1->IsBreakPoint()) return break_point1 == break_point2;
+ return BreakPoint::cast(break_point1)->id() ==
+ BreakPoint::cast(break_point2)->id();
}
+} // namespace
// Remove the specified break point object.
void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
@@ -190,7 +207,7 @@ void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
if (break_point_info->break_point_objects()->IsUndefined(isolate)) return;
// If there is a single break point clear it if it is the same.
if (!break_point_info->break_point_objects()->IsFixedArray()) {
- if (break_point_info->break_point_objects() == *break_point_object) {
+ if (IsEqual(break_point_info->break_point_objects(), *break_point_object)) {
break_point_info->set_break_point_objects(
isolate->heap()->undefined_value());
}
@@ -204,7 +221,7 @@ void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
isolate->factory()->NewFixedArray(old_array->length() - 1);
int found_count = 0;
for (int i = 0; i < old_array->length(); i++) {
- if (old_array->get(i) == *break_point_object) {
+ if (IsEqual(old_array->get(i), *break_point_object)) {
DCHECK(found_count == 0);
found_count++;
} else {
@@ -242,7 +259,7 @@ void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
isolate->factory()->NewFixedArray(old_array->length() + 1);
for (int i = 0; i < old_array->length(); i++) {
// If the break point was there before just ignore.
- if (old_array->get(i) == *break_point_object) return;
+ if (IsEqual(old_array->get(i), *break_point_object)) return;
new_array->set(i, old_array->get(i));
}
// Add the new break point.
@@ -260,12 +277,13 @@ bool BreakPointInfo::HasBreakPointObject(
}
// Single break point.
if (!break_point_info->break_point_objects()->IsFixedArray()) {
- return break_point_info->break_point_objects() == *break_point_object;
+ return IsEqual(break_point_info->break_point_objects(),
+ *break_point_object);
}
// Multiple break points.
FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
for (int i = 0; i < array->length(); i++) {
- if (array->get(i) == *break_point_object) {
+ if (IsEqual(array->get(i), *break_point_object)) {
return true;
}
}
@@ -333,5 +351,25 @@ void CoverageInfo::ResetBlockCount(int slot_index) {
set(slot_start + kSlotBlockCountIndex, Smi::kZero);
}
+void CoverageInfo::Print(String* function_name) {
+ DCHECK(FLAG_trace_block_coverage);
+ DisallowHeapAllocation no_gc;
+
+ OFStream os(stdout);
+ os << "Coverage info (";
+ if (function_name->length() > 0) {
+ auto function_name_cstr = function_name->ToCString();
+ os << function_name_cstr.get();
+ } else {
+ os << "{anonymous}";
+ }
+ os << "):" << std::endl;
+
+ for (int i = 0; i < SlotCount(); i++) {
+ os << "{" << StartSourcePosition(i) << "," << EndSourcePosition(i) << "}"
+ << std::endl;
+ }
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/objects/debug-objects.h b/deps/v8/src/objects/debug-objects.h
index 1c874fc77d..e75043f8d2 100644
--- a/deps/v8/src/objects/debug-objects.h
+++ b/deps/v8/src/objects/debug-objects.h
@@ -20,7 +20,8 @@ class DebugInfo : public Struct {
enum Flag {
kNone = 0,
kHasBreakInfo = 1 << 0,
- kHasCoverageInfo = 1 << 1,
+ kPreparedForBreakpoints = 1 << 1,
+ kHasCoverageInfo = 2 << 1,
};
typedef base::Flags<Flag> Flags;
@@ -41,6 +42,8 @@ class DebugInfo : public Struct {
bool HasBreakInfo() const;
+ bool IsPreparedForBreakpoints() const;
+
// Clears all fields related to break points. Returns true iff the
// DebugInfo is now empty.
bool ClearBreakInfo();
@@ -68,11 +71,9 @@ class DebugInfo : public Struct {
int GetBreakPointCount();
inline bool HasDebugBytecodeArray();
- inline bool HasDebugCode();
inline BytecodeArray* OriginalBytecodeArray();
inline BytecodeArray* DebugBytecodeArray();
- inline Code* DebugCode();
// --- Block Coverage ---
// ----------------------
@@ -162,6 +163,9 @@ class CoverageInfo : public FixedArray {
DECL_CAST(CoverageInfo)
+ // Print debug info.
+ void Print(String* function_name);
+
private:
static int FirstIndexForSlot(int slot_index) {
return kFirstSlotIndex + slot_index * kSlotIndexCount;
@@ -179,6 +183,21 @@ class CoverageInfo : public FixedArray {
DISALLOW_IMPLICIT_CONSTRUCTORS(CoverageInfo);
};
+// Holds breakpoint related information. This object is used by inspector.
+class BreakPoint : public Tuple2 {
+ public:
+ DECL_INT_ACCESSORS(id)
+ DECL_ACCESSORS(condition, String)
+
+ DECL_CAST(BreakPoint)
+
+ static const int kIdOffset = kValue1Offset;
+ static const int kConditionOffset = kValue2Offset;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPoint);
+};
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/objects/descriptor-array.h b/deps/v8/src/objects/descriptor-array.h
index 0dd5742e93..b74b1dac7c 100644
--- a/deps/v8/src/objects/descriptor-array.h
+++ b/deps/v8/src/objects/descriptor-array.h
@@ -161,9 +161,6 @@ class DescriptorArray : public FixedArray {
// Is the descriptor array sorted and without duplicates?
bool IsSortedNoDuplicates(int valid_descriptors = -1);
- // Is the descriptor array consistent with the back pointers in targets?
- bool IsConsistentWithBackPointers(Map* current_map);
-
// Are two DescriptorArrays equal?
bool IsEqualTo(DescriptorArray* other);
#endif
diff --git a/deps/v8/src/objects/dictionary.h b/deps/v8/src/objects/dictionary.h
index bb8e63b267..a989c8fc8a 100644
--- a/deps/v8/src/objects/dictionary.h
+++ b/deps/v8/src/objects/dictionary.h
@@ -112,7 +112,7 @@ class NameDictionaryShape : public BaseDictionaryShape<Handle<Name>> {
static inline uint32_t Hash(Isolate* isolate, Handle<Name> key);
static inline uint32_t HashForObject(Isolate* isolate, Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
- static const int kPrefixSize = 1;
+ static const int kPrefixSize = 2;
static const int kEntrySize = 3;
static const int kEntryValueIndex = 1;
static const bool kNeedsHoleCheck = false;
@@ -125,6 +125,7 @@ class BaseNameDictionary : public Dictionary<Derived, Shape> {
public:
static const int kNextEnumerationIndexIndex =
HashTableBase::kPrefixStartIndex;
+ static const int kObjectHashIndex = kNextEnumerationIndexIndex + 1;
static const int kEntryValueIndex = 1;
// Accessors for next enumeration index.
@@ -137,6 +138,16 @@ class BaseNameDictionary : public Dictionary<Derived, Shape> {
return Smi::ToInt(this->get(kNextEnumerationIndexIndex));
}
+ void SetHash(int masked_hash) {
+ DCHECK_EQ(masked_hash & JSReceiver::kHashMask, masked_hash);
+ this->set(kObjectHashIndex, Smi::FromInt(masked_hash));
+ }
+
+ int Hash() const {
+ Object* hash_obj = this->get(kObjectHashIndex);
+ return Smi::ToInt(hash_obj);
+ }
+
// Creates a new dictionary.
MUST_USE_RESULT static Handle<Derived> New(
Isolate* isolate, int at_least_space_for,
@@ -171,7 +182,10 @@ class NameDictionary
static const int kEntryDetailsIndex = 2;
static const int kInitialCapacity = 2;
+
inline Name* NameAt(int entry);
+ inline void set_hash(int hash);
+ inline int hash() const;
};
class GlobalDictionaryShape : public NameDictionaryShape {
diff --git a/deps/v8/src/objects/hash-table.h b/deps/v8/src/objects/hash-table.h
index 90146c8f29..6b5682535a 100644
--- a/deps/v8/src/objects/hash-table.h
+++ b/deps/v8/src/objects/hash-table.h
@@ -271,6 +271,7 @@ class ObjectHashTableShape : public BaseShape<Handle<Object>> {
static inline uint32_t HashForObject(Isolate* isolate, Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key);
static const int kPrefixSize = 0;
+ static const int kEntryValueIndex = 1;
static const int kEntrySize = 2;
static const bool kNeedsHoleCheck = false;
};
@@ -311,16 +312,16 @@ class ObjectHashTable
Handle<Object> key, bool* was_present,
int32_t hash);
+ // Returns the index to the value of an entry.
+ static inline int EntryToValueIndex(int entry) {
+ return EntryToIndex(entry) + ObjectHashTableShape::kEntryValueIndex;
+ }
+
protected:
friend class MarkCompactCollector;
void AddEntry(int entry, Object* key, Object* value);
void RemoveEntry(int entry);
-
- // Returns the index to the value of an entry.
- static inline int EntryToValueIndex(int entry) {
- return EntryToIndex(entry) + 1;
- }
};
class ObjectHashSetShape : public ObjectHashTableShape {
diff --git a/deps/v8/src/objects/intl-objects.cc b/deps/v8/src/objects/intl-objects.cc
index fd6546b390..f889e6899b 100644
--- a/deps/v8/src/objects/intl-objects.cc
+++ b/deps/v8/src/objects/intl-objects.cc
@@ -14,6 +14,7 @@
#include "src/factory.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
+#include "src/property-descriptor.h"
#include "unicode/brkiter.h"
#include "unicode/bytestream.h"
#include "unicode/calendar.h"
@@ -27,6 +28,7 @@
#include "unicode/locid.h"
#include "unicode/numfmt.h"
#include "unicode/numsys.h"
+#include "unicode/plurrule.h"
#include "unicode/rbbi.h"
#include "unicode/smpdtfmt.h"
#include "unicode/timezone.h"
@@ -34,6 +36,7 @@
#include "unicode/ucol.h"
#include "unicode/ucurr.h"
#include "unicode/unum.h"
+#include "unicode/upluralrules.h"
#include "unicode/uvernum.h"
#include "unicode/uversion.h"
@@ -48,12 +51,13 @@ namespace {
bool ExtractStringSetting(Isolate* isolate, Handle<JSObject> options,
const char* key, icu::UnicodeString* setting) {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(key);
Handle<Object> object =
JSReceiver::GetProperty(options, str).ToHandleChecked();
if (object->IsString()) {
v8::String::Utf8Value utf8_string(
- v8::Utils::ToLocal(Handle<String>::cast(object)));
+ v8_isolate, v8::Utils::ToLocal(Handle<String>::cast(object)));
*setting = icu::UnicodeString::fromUTF8(*utf8_string);
return true;
}
@@ -237,6 +241,42 @@ void SetResolvedDateSettings(Isolate* isolate, const icu::Locale& icu_locale,
}
}
+void SetNumericSettings(Isolate* isolate, icu::DecimalFormat* number_format,
+ Handle<JSObject> options) {
+ int32_t digits;
+ if (ExtractIntegerSetting(isolate, options, "minimumIntegerDigits",
+ &digits)) {
+ number_format->setMinimumIntegerDigits(digits);
+ }
+
+ if (ExtractIntegerSetting(isolate, options, "minimumFractionDigits",
+ &digits)) {
+ number_format->setMinimumFractionDigits(digits);
+ }
+
+ if (ExtractIntegerSetting(isolate, options, "maximumFractionDigits",
+ &digits)) {
+ number_format->setMaximumFractionDigits(digits);
+ }
+
+ bool significant_digits_used = false;
+ if (ExtractIntegerSetting(isolate, options, "minimumSignificantDigits",
+ &digits)) {
+ number_format->setMinimumSignificantDigits(digits);
+ significant_digits_used = true;
+ }
+
+ if (ExtractIntegerSetting(isolate, options, "maximumSignificantDigits",
+ &digits)) {
+ number_format->setMaximumSignificantDigits(digits);
+ significant_digits_used = true;
+ }
+
+ number_format->setSignificantDigitsUsed(significant_digits_used);
+
+ number_format->setRoundingMode(icu::DecimalFormat::kRoundHalfUp);
+}
+
icu::DecimalFormat* CreateICUNumberFormat(Isolate* isolate,
const icu::Locale& icu_locale,
Handle<JSObject> options) {
@@ -305,102 +345,20 @@ icu::DecimalFormat* CreateICUNumberFormat(Isolate* isolate,
number_format->setCurrency(currency.getBuffer(), status);
}
- int32_t digits;
- if (ExtractIntegerSetting(isolate, options, "minimumIntegerDigits",
- &digits)) {
- number_format->setMinimumIntegerDigits(digits);
- }
-
- if (ExtractIntegerSetting(isolate, options, "minimumFractionDigits",
- &digits)) {
- number_format->setMinimumFractionDigits(digits);
- }
-
- if (ExtractIntegerSetting(isolate, options, "maximumFractionDigits",
- &digits)) {
- number_format->setMaximumFractionDigits(digits);
- }
-
- bool significant_digits_used = false;
- if (ExtractIntegerSetting(isolate, options, "minimumSignificantDigits",
- &digits)) {
- number_format->setMinimumSignificantDigits(digits);
- significant_digits_used = true;
- }
-
- if (ExtractIntegerSetting(isolate, options, "maximumSignificantDigits",
- &digits)) {
- number_format->setMaximumSignificantDigits(digits);
- significant_digits_used = true;
- }
-
- number_format->setSignificantDigitsUsed(significant_digits_used);
+ SetNumericSettings(isolate, number_format, options);
bool grouping;
if (ExtractBooleanSetting(isolate, options, "useGrouping", &grouping)) {
number_format->setGroupingUsed(grouping);
}
- // Set rounding mode.
- number_format->setRoundingMode(icu::DecimalFormat::kRoundHalfUp);
-
return number_format;
}
-void SetResolvedNumberSettings(Isolate* isolate, const icu::Locale& icu_locale,
- icu::DecimalFormat* number_format,
- Handle<JSObject> resolved) {
+void SetResolvedNumericSettings(Isolate* isolate, const icu::Locale& icu_locale,
+ icu::DecimalFormat* number_format,
+ Handle<JSObject> resolved) {
Factory* factory = isolate->factory();
- icu::UnicodeString pattern;
- number_format->toPattern(pattern);
- JSObject::SetProperty(
- resolved, factory->intl_pattern_symbol(),
- factory
- ->NewStringFromTwoByte(Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
- pattern.length()))
- .ToHandleChecked(),
- SLOPPY)
- .Assert();
-
- // Set resolved currency code in options.currency if not empty.
- icu::UnicodeString currency(number_format->getCurrency());
- if (!currency.isEmpty()) {
- JSObject::SetProperty(
- resolved, factory->NewStringFromStaticChars("currency"),
- factory
- ->NewStringFromTwoByte(Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(currency.getBuffer()),
- currency.length()))
- .ToHandleChecked(),
- SLOPPY)
- .Assert();
- }
-
- // Ugly hack. ICU doesn't expose numbering system in any way, so we have
- // to assume that for given locale NumberingSystem constructor produces the
- // same digits as NumberFormat/Calendar would.
- UErrorCode status = U_ZERO_ERROR;
- icu::NumberingSystem* numbering_system =
- icu::NumberingSystem::createInstance(icu_locale, status);
- if (U_SUCCESS(status)) {
- const char* ns = numbering_system->getName();
- JSObject::SetProperty(resolved,
- factory->NewStringFromStaticChars("numberingSystem"),
- factory->NewStringFromAsciiChecked(ns), SLOPPY)
- .Assert();
- } else {
- JSObject::SetProperty(resolved,
- factory->NewStringFromStaticChars("numberingSystem"),
- factory->undefined_value(), SLOPPY)
- .Assert();
- }
- delete numbering_system;
-
- JSObject::SetProperty(
- resolved, factory->NewStringFromStaticChars("useGrouping"),
- factory->ToBoolean(number_format->isGroupingUsed()), SLOPPY)
- .Assert();
JSObject::SetProperty(
resolved, factory->NewStringFromStaticChars("minimumIntegerDigits"),
@@ -445,7 +403,7 @@ void SetResolvedNumberSettings(Isolate* isolate, const icu::Locale& icu_locale,
// Set the locale
char result[ULOC_FULLNAME_CAPACITY];
- status = U_ZERO_ERROR;
+ UErrorCode status = U_ZERO_ERROR;
uloc_toLanguageTag(icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY,
FALSE, &status);
if (U_SUCCESS(status)) {
@@ -460,6 +418,53 @@ void SetResolvedNumberSettings(Isolate* isolate, const icu::Locale& icu_locale,
}
}
+void SetResolvedNumberSettings(Isolate* isolate, const icu::Locale& icu_locale,
+ icu::DecimalFormat* number_format,
+ Handle<JSObject> resolved) {
+ Factory* factory = isolate->factory();
+
+ // Set resolved currency code in options.currency if not empty.
+ icu::UnicodeString currency(number_format->getCurrency());
+ if (!currency.isEmpty()) {
+ JSObject::SetProperty(
+ resolved, factory->NewStringFromStaticChars("currency"),
+ factory
+ ->NewStringFromTwoByte(Vector<const uint16_t>(
+ reinterpret_cast<const uint16_t*>(currency.getBuffer()),
+ currency.length()))
+ .ToHandleChecked(),
+ SLOPPY)
+ .Assert();
+ }
+
+ // Ugly hack. ICU doesn't expose numbering system in any way, so we have
+ // to assume that for given locale NumberingSystem constructor produces the
+ // same digits as NumberFormat/Calendar would.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::NumberingSystem* numbering_system =
+ icu::NumberingSystem::createInstance(icu_locale, status);
+ if (U_SUCCESS(status)) {
+ const char* ns = numbering_system->getName();
+ JSObject::SetProperty(resolved,
+ factory->NewStringFromStaticChars("numberingSystem"),
+ factory->NewStringFromAsciiChecked(ns), SLOPPY)
+ .Assert();
+ } else {
+ JSObject::SetProperty(resolved,
+ factory->NewStringFromStaticChars("numberingSystem"),
+ factory->undefined_value(), SLOPPY)
+ .Assert();
+ }
+ delete numbering_system;
+
+ JSObject::SetProperty(
+ resolved, factory->NewStringFromStaticChars("useGrouping"),
+ factory->ToBoolean(number_format->isGroupingUsed()), SLOPPY)
+ .Assert();
+
+ SetResolvedNumericSettings(isolate, icu_locale, number_format, resolved);
+}
+
icu::Collator* CreateICUCollator(Isolate* isolate,
const icu::Locale& icu_locale,
Handle<JSObject> options) {
@@ -644,6 +649,88 @@ void SetResolvedCollatorSettings(Isolate* isolate,
}
}
+bool CreateICUPluralRules(Isolate* isolate, const icu::Locale& icu_locale,
+ Handle<JSObject> options, icu::PluralRules** pl,
+ icu::DecimalFormat** nf) {
+ // Make formatter from options. Numbering system is added
+ // to the locale as Unicode extension (if it was specified at all).
+ UErrorCode status = U_ZERO_ERROR;
+
+ UPluralType type = UPLURAL_TYPE_CARDINAL;
+
+ icu::UnicodeString type_string;
+ if (ExtractStringSetting(isolate, options, "type", &type_string)) {
+ if (type_string == UNICODE_STRING_SIMPLE("ordinal")) {
+ type = UPLURAL_TYPE_ORDINAL;
+ } else {
+ CHECK(type_string == UNICODE_STRING_SIMPLE("cardinal"));
+ }
+ }
+
+ icu::PluralRules* plural_rules =
+ icu::PluralRules::forLocale(icu_locale, type, status);
+
+ if (U_FAILURE(status)) {
+ delete plural_rules;
+ return false;
+ }
+
+ icu::DecimalFormat* number_format = static_cast<icu::DecimalFormat*>(
+ icu::NumberFormat::createInstance(icu_locale, UNUM_DECIMAL, status));
+
+ if (U_FAILURE(status)) {
+ delete plural_rules;
+ delete number_format;
+ return false;
+ }
+
+ *pl = plural_rules;
+ *nf = number_format;
+
+ SetNumericSettings(isolate, number_format, options);
+
+ // Set rounding mode.
+
+ return true;
+}
+
+bool SetResolvedPluralRulesSettings(Isolate* isolate,
+ const icu::Locale& icu_locale,
+ icu::PluralRules* plural_rules,
+ icu::DecimalFormat* number_format,
+ Handle<JSObject> resolved) {
+ SetResolvedNumericSettings(isolate, icu_locale, number_format, resolved);
+
+ Factory* factory = isolate->factory();
+
+ Handle<JSObject> pluralCategories = Handle<JSObject>::cast(
+ JSObject::GetProperty(
+ resolved, factory->NewStringFromStaticChars("pluralCategories"))
+ .ToHandleChecked());
+
+ UErrorCode status = U_ZERO_ERROR;
+ std::unique_ptr<icu::StringEnumeration> categories(
+ plural_rules->getKeywords(status));
+ if (U_FAILURE(status)) return false;
+
+ if (U_FAILURE(status)) return false;
+
+ for (int32_t i = 0;; i++) {
+ const icu::UnicodeString* category = categories->snext(status);
+ if (U_FAILURE(status)) return false;
+ if (category == NULL) return true;
+
+ std::string keyword;
+ Handle<String> value = factory->NewStringFromAsciiChecked(
+ category->toUTF8String(keyword).data());
+
+ LookupIterator it(isolate, pluralCategories, i, LookupIterator::OWN);
+ JSObject::DefineOwnPropertyIgnoreAttributes(&it, value,
+ PropertyAttributes::NONE)
+ .ToHandleChecked();
+ }
+}
+
icu::BreakIterator* CreateICUBreakIterator(Isolate* isolate,
const icu::Locale& icu_locale,
Handle<JSObject> options) {
@@ -704,12 +791,13 @@ void SetResolvedBreakIteratorSettings(Isolate* isolate,
icu::SimpleDateFormat* DateFormat::InitializeDateTimeFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
// Convert BCP47 into ICU locale format.
UErrorCode status = U_ZERO_ERROR;
icu::Locale icu_locale;
char icu_result[ULOC_FULLNAME_CAPACITY];
int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
+ v8::String::Utf8Value bcp47_locale(v8_isolate, v8::Utils::ToLocal(locale));
if (bcp47_locale.length() != 0) {
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
@@ -753,12 +841,14 @@ void DateFormat::DeleteDateFormat(const v8::WeakCallbackInfo<void>& data) {
icu::DecimalFormat* NumberFormat::InitializeNumberFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
+
// Convert BCP47 into ICU locale format.
UErrorCode status = U_ZERO_ERROR;
icu::Locale icu_locale;
char icu_result[ULOC_FULLNAME_CAPACITY];
int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
+ v8::String::Utf8Value bcp47_locale(v8_isolate, v8::Utils::ToLocal(locale));
if (bcp47_locale.length() != 0) {
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
@@ -804,12 +894,13 @@ icu::Collator* Collator::InitializeCollator(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved) {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
// Convert BCP47 into ICU locale format.
UErrorCode status = U_ZERO_ERROR;
icu::Locale icu_locale;
char icu_result[ULOC_FULLNAME_CAPACITY];
int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
+ v8::String::Utf8Value bcp47_locale(v8_isolate, v8::Utils::ToLocal(locale));
if (bcp47_locale.length() != 0) {
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
@@ -849,15 +940,76 @@ void Collator::DeleteCollator(const v8::WeakCallbackInfo<void>& data) {
GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
}
+bool PluralRules::InitializePluralRules(Isolate* isolate, Handle<String> locale,
+ Handle<JSObject> options,
+ Handle<JSObject> resolved,
+ icu::PluralRules** plural_rules,
+ icu::DecimalFormat** number_format) {
+ // Convert BCP47 into ICU locale format.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Locale icu_locale;
+ char locale_name[ULOC_FULLNAME_CAPACITY];
+ int icu_length = 0;
+ v8::String::Utf8Value bcp47_locale(reinterpret_cast<v8::Isolate*>(isolate),
+ v8::Utils::ToLocal(locale));
+ if (bcp47_locale.length() != 0) {
+ uloc_forLanguageTag(*bcp47_locale, locale_name, ULOC_FULLNAME_CAPACITY,
+ &icu_length, &status);
+ if (U_FAILURE(status) || icu_length == 0) {
+ return false;
+ }
+ icu_locale = icu::Locale(locale_name);
+ }
+
+ bool success = CreateICUPluralRules(isolate, icu_locale, options,
+ plural_rules, number_format);
+ if (!success) {
+ // Remove extensions and try again.
+ icu::Locale no_extension_locale(icu_locale.getBaseName());
+ success = CreateICUPluralRules(isolate, no_extension_locale, options,
+ plural_rules, number_format);
+
+ if (!success) {
+ FATAL("Failed to create ICU PluralRules, are ICU data files missing?");
+ }
+
+ // Set resolved settings (pattern, numbering system).
+ success = SetResolvedPluralRulesSettings(
+ isolate, no_extension_locale, *plural_rules, *number_format, resolved);
+ } else {
+ success = SetResolvedPluralRulesSettings(isolate, icu_locale, *plural_rules,
+ *number_format, resolved);
+ }
+
+ return success;
+}
+
+icu::PluralRules* PluralRules::UnpackPluralRules(Isolate* isolate,
+ Handle<JSObject> obj) {
+ return reinterpret_cast<icu::PluralRules*>(obj->GetEmbedderField(0));
+}
+
+icu::DecimalFormat* PluralRules::UnpackNumberFormat(Isolate* isolate,
+ Handle<JSObject> obj) {
+ return reinterpret_cast<icu::DecimalFormat*>(obj->GetEmbedderField(1));
+}
+
+void PluralRules::DeletePluralRules(const v8::WeakCallbackInfo<void>& data) {
+ delete reinterpret_cast<icu::PluralRules*>(data.GetInternalField(0));
+ delete reinterpret_cast<icu::DecimalFormat*>(data.GetInternalField(1));
+ GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
+}
+
icu::BreakIterator* V8BreakIterator::InitializeBreakIterator(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
// Convert BCP47 into ICU locale format.
UErrorCode status = U_ZERO_ERROR;
icu::Locale icu_locale;
char icu_result[ULOC_FULLNAME_CAPACITY];
int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
+ v8::String::Utf8Value bcp47_locale(v8_isolate, v8::Utils::ToLocal(locale));
if (bcp47_locale.length() != 0) {
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
diff --git a/deps/v8/src/objects/intl-objects.h b/deps/v8/src/objects/intl-objects.h
index 890a21d074..d4bdb1e067 100644
--- a/deps/v8/src/objects/intl-objects.h
+++ b/deps/v8/src/objects/intl-objects.h
@@ -16,6 +16,7 @@ namespace U_ICU_NAMESPACE {
class BreakIterator;
class Collator;
class DecimalFormat;
+class PluralRules;
class SimpleDateFormat;
}
@@ -98,6 +99,43 @@ class Collator {
Collator();
};
+class PluralRules {
+ public:
+ // Create a PluralRules and DecimalFormat for the specificied locale and
+ // options. Returns false on an ICU failure.
+ static bool InitializePluralRules(Isolate* isolate, Handle<String> locale,
+ Handle<JSObject> options,
+ Handle<JSObject> resolved,
+ icu::PluralRules** plural_rules,
+ icu::DecimalFormat** decimal_format);
+
+ // Unpacks PluralRules object from corresponding JavaScript object.
+ static icu::PluralRules* UnpackPluralRules(Isolate* isolate,
+ Handle<JSObject> obj);
+
+ // Unpacks NumberFormat object from corresponding JavaScript PluralRUles
+ // object.
+ static icu::DecimalFormat* UnpackNumberFormat(Isolate* isolate,
+ Handle<JSObject> obj);
+
+ // Release memory we allocated for the Collator once the JS object that holds
+ // the pointer gets garbage collected.
+ static void DeletePluralRules(const v8::WeakCallbackInfo<void>& data);
+
+ // Layout description.
+ static const int kPluralRules = JSObject::kHeaderSize;
+ // Values are formatted with this NumberFormat and then parsed as a Number
+ // to round them based on the options passed into the PluralRules objct.
+ // TODO(littledan): If a future version of ICU supports the rounding
+ // built-in to PluralRules, switch to that, see this bug:
+ // http://bugs.icu-project.org/trac/ticket/12763
+ static const int kNumberFormat = kPluralRules + kPointerSize;
+ static const int kSize = kNumberFormat + kPointerSize;
+
+ private:
+ PluralRules();
+};
+
class V8BreakIterator {
public:
// Create a BreakIterator for the specificied locale and options. Returns the
diff --git a/deps/v8/src/objects/literal-objects.h b/deps/v8/src/objects/literal-objects.h
index f544ee37b8..74a5afde42 100644
--- a/deps/v8/src/objects/literal-objects.h
+++ b/deps/v8/src/objects/literal-objects.h
@@ -45,6 +45,8 @@ class ConstantElementsPair : public Tuple2 {
DECL_INT_ACCESSORS(elements_kind)
DECL_ACCESSORS(constant_values, FixedArrayBase)
+ inline bool is_empty() const;
+
DECL_CAST(ConstantElementsPair)
static const int kElementsKindOffset = kValue1Offset;
diff --git a/deps/v8/src/objects/map.h b/deps/v8/src/objects/map.h
index 2fa992e153..114ec0b430 100644
--- a/deps/v8/src/objects/map.h
+++ b/deps/v8/src/objects/map.h
@@ -23,6 +23,7 @@ namespace internal {
V(Code) \
V(ConsString) \
V(DataObject) \
+ V(FeedbackVector) \
V(FixedArray) \
V(FixedDoubleArray) \
V(FixedFloat64Array) \
@@ -142,7 +143,7 @@ class Map : public HeapObject {
class IsMigrationTarget : public BitField<bool, 25, 1> {};
class ImmutablePrototype : public BitField<bool, 26, 1> {};
class NewTargetIsBase : public BitField<bool, 27, 1> {};
- // Bit 28 is free.
+ class MayHaveInterestingSymbols : public BitField<bool, 28, 1> {};
// Keep this bit field at the very end for better code in
// Builtins::kJSConstructStubGeneric stub.
@@ -218,6 +219,13 @@ class Map : public HeapObject {
inline void set_is_constructor(bool value);
inline bool is_constructor() const;
+ // Tells whether the instance with this map may have properties for
+ // interesting symbols on it.
+ // An "interesting symbol" is one for which Name::IsInterestingSymbol()
+ // returns true, i.e. a well-known symbol like @@toStringTag.
+ inline void set_may_have_interesting_symbols(bool value);
+ inline bool may_have_interesting_symbols() const;
+
// Tells whether the instance with this map has a hidden prototype.
inline void set_has_hidden_prototype(bool value);
inline bool has_hidden_prototype() const;
@@ -250,6 +258,7 @@ class Map : public HeapObject {
inline bool is_extensible() const;
inline void set_is_prototype_map(bool value);
inline bool is_prototype_map() const;
+ inline bool is_abandoned_prototype_map() const;
inline void set_elements_kind(ElementsKind elements_kind);
inline ElementsKind elements_kind() const;
@@ -275,7 +284,7 @@ class Map : public HeapObject {
// map with DICTIONARY_ELEMENTS was found in the prototype chain.
bool DictionaryElementsInPrototypeChainOnly();
- inline Map* ElementsTransitionMap() const;
+ inline Map* ElementsTransitionMap();
inline FixedArrayBase* GetInitialElements() const;
@@ -311,7 +320,7 @@ class Map : public HeapObject {
// Returns a WeakCell object containing given prototype. The cell is cached
// in PrototypeInfo which is created lazily.
static Handle<WeakCell> GetOrCreatePrototypeWeakCell(
- Handle<JSObject> prototype, Isolate* isolate);
+ Handle<JSReceiver> prototype, Isolate* isolate);
Map* FindRootMap() const;
Map* FindFieldOwner(int descriptor) const;
@@ -519,12 +528,10 @@ class Map : public HeapObject {
// transitions to avoid an explosion in the number of maps for objects used as
// dictionaries.
inline bool TooManyFastProperties(StoreFromKeyed store_mode) const;
- static Handle<Map> TransitionToDataProperty(Handle<Map> map,
- Handle<Name> name,
- Handle<Object> value,
- PropertyAttributes attributes,
- PropertyConstness constness,
- StoreFromKeyed store_mode);
+ static Handle<Map> TransitionToDataProperty(
+ Handle<Map> map, Handle<Name> name, Handle<Object> value,
+ PropertyAttributes attributes, PropertyConstness constness,
+ StoreFromKeyed store_mode, bool* created_new_map);
static Handle<Map> TransitionToAccessorProperty(
Isolate* isolate, Handle<Map> map, Handle<Name> name, int descriptor,
Handle<Object> getter, Handle<Object> setter,
@@ -602,8 +609,6 @@ class Map : public HeapObject {
inline bool IsSpecialReceiverMap() const;
- inline bool CanOmitMapChecks() const;
-
static void AddDependentCode(Handle<Map> map,
DependentCode::DependencyGroup group,
Handle<Code> code);
@@ -618,7 +623,6 @@ class Map : public HeapObject {
#ifdef VERIFY_HEAP
void DictionaryMapVerify();
- void VerifyOmittedMapChecks();
#endif
inline int visitor_id() const;
diff --git a/deps/v8/src/objects/module-info.h b/deps/v8/src/objects/module-info.h
deleted file mode 100644
index b797db7156..0000000000
--- a/deps/v8/src/objects/module-info.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2017 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_OBJECTS_MODULE_INFO_H_
-#define V8_OBJECTS_MODULE_INFO_H_
-
-#include "src/objects.h"
-
-// Has to be the last include (doesn't have include guards):
-#include "src/objects/object-macros.h"
-
-namespace v8 {
-namespace internal {
-
-template <typename T>
-class Handle;
-class Isolate;
-class ModuleDescriptor;
-class ModuleInfoEntry;
-class String;
-class Zone;
-
-// ModuleInfo is to ModuleDescriptor what ScopeInfo is to Scope.
-class ModuleInfo : public FixedArray {
- public:
- DECL_CAST(ModuleInfo)
-
- static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone,
- ModuleDescriptor* descr);
-
- inline FixedArray* module_requests() const {
- return FixedArray::cast(get(kModuleRequestsIndex));
- }
-
- inline FixedArray* special_exports() const {
- return FixedArray::cast(get(kSpecialExportsIndex));
- }
-
- inline FixedArray* regular_exports() const {
- return FixedArray::cast(get(kRegularExportsIndex));
- }
-
- inline FixedArray* regular_imports() const {
- return FixedArray::cast(get(kRegularImportsIndex));
- }
-
- inline FixedArray* namespace_imports() const {
- return FixedArray::cast(get(kNamespaceImportsIndex));
- }
-
- inline FixedArray* module_request_positions() const {
- return FixedArray::cast(get(kModuleRequestPositionsIndex));
- }
-
- // Accessors for [regular_exports].
- int RegularExportCount() const;
- String* RegularExportLocalName(int i) const;
- int RegularExportCellIndex(int i) const;
- FixedArray* RegularExportExportNames(int i) const;
-
-#ifdef DEBUG
- inline bool Equals(ModuleInfo* other) const {
- return regular_exports() == other->regular_exports() &&
- regular_imports() == other->regular_imports() &&
- special_exports() == other->special_exports() &&
- namespace_imports() == other->namespace_imports() &&
- module_requests() == other->module_requests() &&
- module_request_positions() == other->module_request_positions();
- }
-#endif
-
- private:
- friend class Factory;
- friend class ModuleDescriptor;
- enum {
- kModuleRequestsIndex,
- kSpecialExportsIndex,
- kRegularExportsIndex,
- kNamespaceImportsIndex,
- kRegularImportsIndex,
- kModuleRequestPositionsIndex,
- kLength
- };
- enum {
- kRegularExportLocalNameOffset,
- kRegularExportCellIndexOffset,
- kRegularExportExportNamesOffset,
- kRegularExportLength
- };
- DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfo);
-};
-
-class ModuleInfoEntry : public Struct {
- public:
- DECL_CAST(ModuleInfoEntry)
- DECL_PRINTER(ModuleInfoEntry)
- DECL_VERIFIER(ModuleInfoEntry)
-
- DECL_ACCESSORS(export_name, Object)
- DECL_ACCESSORS(local_name, Object)
- DECL_ACCESSORS(import_name, Object)
- DECL_INT_ACCESSORS(module_request)
- DECL_INT_ACCESSORS(cell_index)
- DECL_INT_ACCESSORS(beg_pos)
- DECL_INT_ACCESSORS(end_pos)
-
- static Handle<ModuleInfoEntry> New(Isolate* isolate,
- Handle<Object> export_name,
- Handle<Object> local_name,
- Handle<Object> import_name,
- int module_request, int cell_index,
- int beg_pos, int end_pos);
-
- static const int kExportNameOffset = HeapObject::kHeaderSize;
- static const int kLocalNameOffset = kExportNameOffset + kPointerSize;
- static const int kImportNameOffset = kLocalNameOffset + kPointerSize;
- static const int kModuleRequestOffset = kImportNameOffset + kPointerSize;
- static const int kCellIndexOffset = kModuleRequestOffset + kPointerSize;
- static const int kBegPosOffset = kCellIndexOffset + kPointerSize;
- static const int kEndPosOffset = kBegPosOffset + kPointerSize;
- static const int kSize = kEndPosOffset + kPointerSize;
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfoEntry);
-};
-
-} // namespace internal
-} // namespace v8
-
-#include "src/objects/object-macros-undef.h"
-
-#endif // V8_OBJECTS_MODULE_INFO_H_
diff --git a/deps/v8/src/objects/module-inl.h b/deps/v8/src/objects/module-inl.h
new file mode 100644
index 0000000000..7e5310ff3b
--- /dev/null
+++ b/deps/v8/src/objects/module-inl.h
@@ -0,0 +1,67 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_OBJECTS_MODULE_INL_H_
+#define V8_OBJECTS_MODULE_INL_H_
+
+#include "src/objects/module.h"
+
+// Has to be the last include (doesn't have include guards):
+#include "src/objects/object-macros.h"
+
+namespace v8 {
+namespace internal {
+
+CAST_ACCESSOR(Module)
+ACCESSORS(Module, code, Object, kCodeOffset)
+ACCESSORS(Module, exports, ObjectHashTable, kExportsOffset)
+ACCESSORS(Module, regular_exports, FixedArray, kRegularExportsOffset)
+ACCESSORS(Module, regular_imports, FixedArray, kRegularImportsOffset)
+ACCESSORS(Module, module_namespace, HeapObject, kModuleNamespaceOffset)
+ACCESSORS(Module, requested_modules, FixedArray, kRequestedModulesOffset)
+ACCESSORS(Module, script, Script, kScriptOffset)
+ACCESSORS(Module, exception, Object, kExceptionOffset)
+SMI_ACCESSORS(Module, status, kStatusOffset)
+SMI_ACCESSORS(Module, dfs_index, kDfsIndexOffset)
+SMI_ACCESSORS(Module, dfs_ancestor_index, kDfsAncestorIndexOffset)
+SMI_ACCESSORS(Module, hash, kHashOffset)
+
+ModuleInfo* Module::info() const {
+ if (status() >= kEvaluating) {
+ return ModuleInfo::cast(code());
+ }
+ ScopeInfo* scope_info =
+ status() == kInstantiated
+ ? JSGeneratorObject::cast(code())->function()->shared()->scope_info()
+ : status() == kInstantiating
+ ? JSFunction::cast(code())->shared()->scope_info()
+ : SharedFunctionInfo::cast(code())->scope_info();
+ return scope_info->ModuleDescriptorInfo();
+}
+
+TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE)
+CAST_ACCESSOR(JSModuleNamespace)
+ACCESSORS(JSModuleNamespace, module, Module, kModuleOffset)
+
+CAST_ACCESSOR(ModuleInfoEntry)
+ACCESSORS(ModuleInfoEntry, export_name, Object, kExportNameOffset)
+ACCESSORS(ModuleInfoEntry, local_name, Object, kLocalNameOffset)
+ACCESSORS(ModuleInfoEntry, import_name, Object, kImportNameOffset)
+SMI_ACCESSORS(ModuleInfoEntry, module_request, kModuleRequestOffset)
+SMI_ACCESSORS(ModuleInfoEntry, cell_index, kCellIndexOffset)
+SMI_ACCESSORS(ModuleInfoEntry, beg_pos, kBegPosOffset)
+SMI_ACCESSORS(ModuleInfoEntry, end_pos, kEndPosOffset)
+
+CAST_ACCESSOR(ModuleInfo)
+
+bool HeapObject::IsModuleInfo() const {
+ return map() == GetHeap()->module_info_map();
+}
+
+} // namespace internal
+} // namespace v8
+
+#include "src/objects/object-macros-undef.h"
+
+#endif // V8_OBJECTS_MODULE_INL_H_
diff --git a/deps/v8/src/objects/module.cc b/deps/v8/src/objects/module.cc
new file mode 100644
index 0000000000..a73d91ace8
--- /dev/null
+++ b/deps/v8/src/objects/module.cc
@@ -0,0 +1,873 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <unordered_map>
+#include <unordered_set>
+
+#include "src/objects/module.h"
+
+#include "src/accessors.h"
+#include "src/ast/modules.h"
+#include "src/objects-inl.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+struct ModuleHandleHash {
+ V8_INLINE size_t operator()(Handle<Module> module) const {
+ return module->hash();
+ }
+};
+
+struct ModuleHandleEqual {
+ V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const {
+ return *lhs == *rhs;
+ }
+};
+
+struct StringHandleHash {
+ V8_INLINE size_t operator()(Handle<String> string) const {
+ return string->Hash();
+ }
+};
+
+struct StringHandleEqual {
+ V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const {
+ return lhs->Equals(*rhs);
+ }
+};
+
+class UnorderedStringSet
+ : public std::unordered_set<Handle<String>, StringHandleHash,
+ StringHandleEqual,
+ ZoneAllocator<Handle<String>>> {
+ public:
+ explicit UnorderedStringSet(Zone* zone)
+ : std::unordered_set<Handle<String>, StringHandleHash, StringHandleEqual,
+ ZoneAllocator<Handle<String>>>(
+ 2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
+ ZoneAllocator<Handle<String>>(zone)) {}
+};
+
+class UnorderedModuleSet
+ : public std::unordered_set<Handle<Module>, ModuleHandleHash,
+ ModuleHandleEqual,
+ ZoneAllocator<Handle<Module>>> {
+ public:
+ explicit UnorderedModuleSet(Zone* zone)
+ : std::unordered_set<Handle<Module>, ModuleHandleHash, ModuleHandleEqual,
+ ZoneAllocator<Handle<Module>>>(
+ 2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
+ ZoneAllocator<Handle<Module>>(zone)) {}
+};
+
+class UnorderedStringMap
+ : public std::unordered_map<
+ Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
+ ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>> {
+ public:
+ explicit UnorderedStringMap(Zone* zone)
+ : std::unordered_map<
+ Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
+ ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>>(
+ 2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
+ ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>(
+ zone)) {}
+};
+
+} // anonymous namespace
+
+class Module::ResolveSet
+ : public std::unordered_map<
+ Handle<Module>, UnorderedStringSet*, ModuleHandleHash,
+ ModuleHandleEqual,
+ ZoneAllocator<std::pair<const Handle<Module>, UnorderedStringSet*>>> {
+ public:
+ explicit ResolveSet(Zone* zone)
+ : std::unordered_map<Handle<Module>, UnorderedStringSet*,
+ ModuleHandleHash, ModuleHandleEqual,
+ ZoneAllocator<std::pair<const Handle<Module>,
+ UnorderedStringSet*>>>(
+ 2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
+ ZoneAllocator<std::pair<const Handle<Module>, UnorderedStringSet*>>(
+ zone)),
+ zone_(zone) {}
+
+ Zone* zone() const { return zone_; }
+
+ private:
+ Zone* zone_;
+};
+
+namespace {
+
+int ExportIndex(int cell_index) {
+ DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
+ ModuleDescriptor::kExport);
+ return cell_index - 1;
+}
+
+int ImportIndex(int cell_index) {
+ DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
+ ModuleDescriptor::kImport);
+ return -cell_index - 1;
+}
+
+} // anonymous namespace
+
+void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name,
+ Handle<ModuleInfoEntry> entry) {
+ Isolate* isolate = module->GetIsolate();
+ Handle<ObjectHashTable> exports(module->exports(), isolate);
+ DCHECK(exports->Lookup(name)->IsTheHole(isolate));
+ exports = ObjectHashTable::Put(exports, name, entry);
+ module->set_exports(*exports);
+}
+
+void Module::CreateExport(Handle<Module> module, int cell_index,
+ Handle<FixedArray> names) {
+ DCHECK_LT(0, names->length());
+ Isolate* isolate = module->GetIsolate();
+
+ Handle<Cell> cell =
+ isolate->factory()->NewCell(isolate->factory()->undefined_value());
+ module->regular_exports()->set(ExportIndex(cell_index), *cell);
+
+ Handle<ObjectHashTable> exports(module->exports(), isolate);
+ for (int i = 0, n = names->length(); i < n; ++i) {
+ Handle<String> name(String::cast(names->get(i)), isolate);
+ DCHECK(exports->Lookup(name)->IsTheHole(isolate));
+ exports = ObjectHashTable::Put(exports, name, cell);
+ }
+ module->set_exports(*exports);
+}
+
+Cell* Module::GetCell(int cell_index) {
+ DisallowHeapAllocation no_gc;
+ Object* cell;
+ switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
+ case ModuleDescriptor::kImport:
+ cell = regular_imports()->get(ImportIndex(cell_index));
+ break;
+ case ModuleDescriptor::kExport:
+ cell = regular_exports()->get(ExportIndex(cell_index));
+ break;
+ case ModuleDescriptor::kInvalid:
+ UNREACHABLE();
+ cell = nullptr;
+ break;
+ }
+ return Cell::cast(cell);
+}
+
+Handle<Object> Module::LoadVariable(Handle<Module> module, int cell_index) {
+ Isolate* isolate = module->GetIsolate();
+ return handle(module->GetCell(cell_index)->value(), isolate);
+}
+
+void Module::StoreVariable(Handle<Module> module, int cell_index,
+ Handle<Object> value) {
+ DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
+ ModuleDescriptor::kExport);
+ module->GetCell(cell_index)->set_value(*value);
+}
+
+#ifdef DEBUG
+void Module::PrintStatusTransition(Status new_status) {
+ if (FLAG_trace_module_status) {
+ OFStream os(stdout);
+ os << "Changing module status from " << status() << " to " << new_status
+ << " for ";
+ script()->GetNameOrSourceURL()->Print(os);
+#ifndef OBJECT_PRINT
+ os << "\n";
+#endif // OBJECT_PRINT
+ }
+}
+#endif // DEBUG
+
+void Module::SetStatus(Status new_status) {
+ DisallowHeapAllocation no_alloc;
+ DCHECK_LE(status(), new_status);
+ DCHECK_NE(new_status, Module::kErrored);
+#ifdef DEBUG
+ PrintStatusTransition(new_status);
+#endif // DEBUG
+ set_status(new_status);
+}
+
+void Module::RecordError() {
+ DisallowHeapAllocation no_alloc;
+
+ Isolate* isolate = GetIsolate();
+ Object* the_exception = isolate->pending_exception();
+ DCHECK(!the_exception->IsTheHole(isolate));
+
+ switch (status()) {
+ case Module::kUninstantiated:
+ case Module::kPreInstantiating:
+ case Module::kInstantiating:
+ case Module::kEvaluating:
+ break;
+ case Module::kErrored:
+ DCHECK_EQ(exception(), the_exception);
+ return;
+ default:
+ UNREACHABLE();
+ }
+
+ set_code(info());
+
+ DCHECK(exception()->IsTheHole(isolate));
+#ifdef DEBUG
+ PrintStatusTransition(Module::kErrored);
+#endif // DEBUG
+ set_status(Module::kErrored);
+ set_exception(the_exception);
+}
+
+Object* Module::GetException() {
+ DisallowHeapAllocation no_alloc;
+ DCHECK_EQ(status(), Module::kErrored);
+ Object* the_exception = exception();
+ DCHECK(!the_exception->IsTheHole(GetIsolate()));
+ return the_exception;
+}
+
+MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module,
+ Handle<String> name, int module_request,
+ MessageLocation loc, bool must_resolve,
+ Module::ResolveSet* resolve_set) {
+ Isolate* isolate = module->GetIsolate();
+ Handle<Module> requested_module(
+ Module::cast(module->requested_modules()->get(module_request)), isolate);
+ MaybeHandle<Cell> result = Module::ResolveExport(requested_module, name, loc,
+ must_resolve, resolve_set);
+ if (isolate->has_pending_exception()) {
+ DCHECK(result.is_null());
+ if (must_resolve) module->RecordError();
+ // If {must_resolve} is false and there's an exception, then either that
+ // exception was already recorded where it happened, or it's the
+ // kAmbiguousExport exception (see ResolveExportUsingStarExports) and the
+ // culprit module is still to be determined.
+ }
+ return result;
+}
+
+MaybeHandle<Cell> Module::ResolveExport(Handle<Module> module,
+ Handle<String> name,
+ MessageLocation loc, bool must_resolve,
+ Module::ResolveSet* resolve_set) {
+ DCHECK_NE(module->status(), kErrored);
+ DCHECK_NE(module->status(), kEvaluating);
+ DCHECK_GE(module->status(), kPreInstantiating);
+
+ Isolate* isolate = module->GetIsolate();
+ Handle<Object> object(module->exports()->Lookup(name), isolate);
+ if (object->IsCell()) {
+ // Already resolved (e.g. because it's a local export).
+ return Handle<Cell>::cast(object);
+ }
+
+ // Check for cycle before recursing.
+ {
+ // Attempt insertion with a null string set.
+ auto result = resolve_set->insert({module, nullptr});
+ UnorderedStringSet*& name_set = result.first->second;
+ if (result.second) {
+ // |module| wasn't in the map previously, so allocate a new name set.
+ Zone* zone = resolve_set->zone();
+ name_set =
+ new (zone->New(sizeof(UnorderedStringSet))) UnorderedStringSet(zone);
+ } else if (name_set->count(name)) {
+ // Cycle detected.
+ if (must_resolve) {
+ return isolate->Throw<Cell>(
+ isolate->factory()->NewSyntaxError(
+ MessageTemplate::kCyclicModuleDependency, name),
+ &loc);
+ }
+ return MaybeHandle<Cell>();
+ }
+ name_set->insert(name);
+ }
+
+ if (object->IsModuleInfoEntry()) {
+ // Not yet resolved indirect export.
+ Handle<ModuleInfoEntry> entry = Handle<ModuleInfoEntry>::cast(object);
+ Handle<String> import_name(String::cast(entry->import_name()), isolate);
+ Handle<Script> script(module->script(), isolate);
+ MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
+
+ Handle<Cell> cell;
+ if (!ResolveImport(module, import_name, entry->module_request(), new_loc,
+ true, resolve_set)
+ .ToHandle(&cell)) {
+ DCHECK(isolate->has_pending_exception());
+ return MaybeHandle<Cell>();
+ }
+
+ // The export table may have changed but the entry in question should be
+ // unchanged.
+ Handle<ObjectHashTable> exports(module->exports(), isolate);
+ DCHECK(exports->Lookup(name)->IsModuleInfoEntry());
+
+ exports = ObjectHashTable::Put(exports, name, cell);
+ module->set_exports(*exports);
+ return cell;
+ }
+
+ DCHECK(object->IsTheHole(isolate));
+ return Module::ResolveExportUsingStarExports(module, name, loc, must_resolve,
+ resolve_set);
+}
+
+MaybeHandle<Cell> Module::ResolveExportUsingStarExports(
+ Handle<Module> module, Handle<String> name, MessageLocation loc,
+ bool must_resolve, Module::ResolveSet* resolve_set) {
+ Isolate* isolate = module->GetIsolate();
+ if (!name->Equals(isolate->heap()->default_string())) {
+ // Go through all star exports looking for the given name. If multiple star
+ // exports provide the name, make sure they all map it to the same cell.
+ Handle<Cell> unique_cell;
+ Handle<FixedArray> special_exports(module->info()->special_exports(),
+ isolate);
+ for (int i = 0, n = special_exports->length(); i < n; ++i) {
+ i::Handle<i::ModuleInfoEntry> entry(
+ i::ModuleInfoEntry::cast(special_exports->get(i)), isolate);
+ if (!entry->export_name()->IsUndefined(isolate)) {
+ continue; // Indirect export.
+ }
+
+ Handle<Script> script(module->script(), isolate);
+ MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
+
+ Handle<Cell> cell;
+ if (ResolveImport(module, name, entry->module_request(), new_loc, false,
+ resolve_set)
+ .ToHandle(&cell)) {
+ if (unique_cell.is_null()) unique_cell = cell;
+ if (*unique_cell != *cell) {
+ return isolate->Throw<Cell>(
+ isolate->factory()->NewSyntaxError(
+ MessageTemplate::kAmbiguousExport, name),
+ &loc);
+ }
+ } else if (isolate->has_pending_exception()) {
+ return MaybeHandle<Cell>();
+ }
+ }
+
+ if (!unique_cell.is_null()) {
+ // Found a unique star export for this name.
+ Handle<ObjectHashTable> exports(module->exports(), isolate);
+ DCHECK(exports->Lookup(name)->IsTheHole(isolate));
+ exports = ObjectHashTable::Put(exports, name, unique_cell);
+ module->set_exports(*exports);
+ return unique_cell;
+ }
+ }
+
+ // Unresolvable.
+ if (must_resolve) {
+ return isolate->Throw<Cell>(isolate->factory()->NewSyntaxError(
+ MessageTemplate::kUnresolvableExport, name),
+ &loc);
+ }
+ return MaybeHandle<Cell>();
+}
+
+bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context,
+ v8::Module::ResolveCallback callback) {
+#ifdef DEBUG
+ if (FLAG_trace_module_status) {
+ OFStream os(stdout);
+ os << "Instantiating module ";
+ module->script()->GetNameOrSourceURL()->Print(os);
+#ifndef OBJECT_PRINT
+ os << "\n";
+#endif // OBJECT_PRINT
+ }
+#endif // DEBUG
+
+ Isolate* isolate = module->GetIsolate();
+ if (module->status() == kErrored) {
+ isolate->Throw(module->GetException());
+ return false;
+ }
+
+ if (!PrepareInstantiate(module, context, callback)) {
+ return false;
+ }
+
+ Zone zone(isolate->allocator(), ZONE_NAME);
+ ZoneForwardList<Handle<Module>> stack(&zone);
+ unsigned dfs_index = 0;
+ if (!FinishInstantiate(module, &stack, &dfs_index, &zone)) {
+ for (auto& descendant : stack) {
+ descendant->RecordError();
+ }
+ DCHECK_EQ(module->GetException(), isolate->pending_exception());
+ return false;
+ }
+ DCHECK(module->status() == kInstantiated || module->status() == kEvaluated);
+ DCHECK(stack.empty());
+ return true;
+}
+
+bool Module::PrepareInstantiate(Handle<Module> module,
+ v8::Local<v8::Context> context,
+ v8::Module::ResolveCallback callback) {
+ DCHECK_NE(module->status(), kErrored);
+ DCHECK_NE(module->status(), kEvaluating);
+ DCHECK_NE(module->status(), kInstantiating);
+ if (module->status() >= kPreInstantiating) return true;
+ module->SetStatus(kPreInstantiating);
+
+ // Obtain requested modules.
+ Isolate* isolate = module->GetIsolate();
+ Handle<ModuleInfo> module_info(module->info(), isolate);
+ Handle<FixedArray> module_requests(module_info->module_requests(), isolate);
+ Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
+ for (int i = 0, length = module_requests->length(); i < length; ++i) {
+ Handle<String> specifier(String::cast(module_requests->get(i)), isolate);
+ v8::Local<v8::Module> api_requested_module;
+ if (!callback(context, v8::Utils::ToLocal(specifier),
+ v8::Utils::ToLocal(module))
+ .ToLocal(&api_requested_module)) {
+ isolate->PromoteScheduledException();
+ module->RecordError();
+ return false;
+ }
+ Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module);
+ if (requested_module->status() == kErrored) {
+ // TODO(neis): Move this into callback?
+ isolate->Throw(requested_module->GetException());
+ module->RecordError();
+ DCHECK_EQ(module->GetException(), requested_module->GetException());
+ return false;
+ }
+ requested_modules->set(i, *requested_module);
+ }
+
+ // Recurse.
+ for (int i = 0, length = requested_modules->length(); i < length; ++i) {
+ Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
+ isolate);
+ if (!PrepareInstantiate(requested_module, context, callback)) {
+ module->RecordError();
+ DCHECK_EQ(module->GetException(), requested_module->GetException());
+ return false;
+ }
+ }
+
+ // Set up local exports.
+ // TODO(neis): Create regular_exports array here instead of in factory method?
+ for (int i = 0, n = module_info->RegularExportCount(); i < n; ++i) {
+ int cell_index = module_info->RegularExportCellIndex(i);
+ Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
+ isolate);
+ CreateExport(module, cell_index, export_names);
+ }
+
+ // Partially set up indirect exports.
+ // For each indirect export, we create the appropriate slot in the export
+ // table and store its ModuleInfoEntry there. When we later find the correct
+ // Cell in the module that actually provides the value, we replace the
+ // ModuleInfoEntry by that Cell (see ResolveExport).
+ Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
+ for (int i = 0, n = special_exports->length(); i < n; ++i) {
+ Handle<ModuleInfoEntry> entry(
+ ModuleInfoEntry::cast(special_exports->get(i)), isolate);
+ Handle<Object> export_name(entry->export_name(), isolate);
+ if (export_name->IsUndefined(isolate)) continue; // Star export.
+ CreateIndirectExport(module, Handle<String>::cast(export_name), entry);
+ }
+
+ DCHECK_EQ(module->status(), kPreInstantiating);
+ return true;
+}
+
+void Module::RunInitializationCode(Handle<Module> module) {
+ DCHECK_EQ(module->status(), kInstantiating);
+ Isolate* isolate = module->GetIsolate();
+ Handle<JSFunction> function(JSFunction::cast(module->code()), isolate);
+ DCHECK_EQ(MODULE_SCOPE, function->shared()->scope_info()->scope_type());
+ Handle<Object> receiver = isolate->factory()->undefined_value();
+ Handle<Object> argv[] = {module};
+ Handle<Object> generator =
+ Execution::Call(isolate, function, receiver, arraysize(argv), argv)
+ .ToHandleChecked();
+ DCHECK_EQ(*function, Handle<JSGeneratorObject>::cast(generator)->function());
+ module->set_code(*generator);
+}
+
+void Module::MaybeTransitionComponent(Handle<Module> module,
+ ZoneForwardList<Handle<Module>>* stack,
+ Status new_status) {
+ DCHECK(new_status == kInstantiated || new_status == kEvaluated);
+ SLOW_DCHECK(
+ // {module} is on the {stack}.
+ std::count_if(stack->begin(), stack->end(),
+ [&](Handle<Module> m) { return *m == *module; }) == 1);
+ DCHECK_LE(module->dfs_ancestor_index(), module->dfs_index());
+ if (module->dfs_ancestor_index() == module->dfs_index()) {
+ // This is the root of its strongly connected component.
+ Handle<Module> ancestor;
+ do {
+ ancestor = stack->front();
+ stack->pop_front();
+ DCHECK_EQ(ancestor->status(),
+ new_status == kInstantiated ? kInstantiating : kEvaluating);
+ if (new_status == kInstantiated) RunInitializationCode(ancestor);
+ ancestor->SetStatus(new_status);
+ } while (*ancestor != *module);
+ }
+}
+
+bool Module::FinishInstantiate(Handle<Module> module,
+ ZoneForwardList<Handle<Module>>* stack,
+ unsigned* dfs_index, Zone* zone) {
+ DCHECK_NE(module->status(), kErrored);
+ DCHECK_NE(module->status(), kEvaluating);
+ if (module->status() >= kInstantiating) return true;
+ DCHECK_EQ(module->status(), kPreInstantiating);
+
+ // Instantiate SharedFunctionInfo and mark module as instantiating for
+ // the recursion.
+ Isolate* isolate = module->GetIsolate();
+ Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(module->code()),
+ isolate);
+ Handle<JSFunction> function =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ shared, isolate->native_context());
+ module->set_code(*function);
+ module->SetStatus(kInstantiating);
+ module->set_dfs_index(*dfs_index);
+ module->set_dfs_ancestor_index(*dfs_index);
+ stack->push_front(module);
+ (*dfs_index)++;
+
+ // Recurse.
+ Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
+ for (int i = 0, length = requested_modules->length(); i < length; ++i) {
+ Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
+ isolate);
+ if (!FinishInstantiate(requested_module, stack, dfs_index, zone)) {
+ return false;
+ }
+
+ DCHECK_NE(requested_module->status(), kErrored);
+ DCHECK_NE(requested_module->status(), kEvaluating);
+ DCHECK_GE(requested_module->status(), kInstantiating);
+ SLOW_DCHECK(
+ // {requested_module} is instantiating iff it's on the {stack}.
+ (requested_module->status() == kInstantiating) ==
+ std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
+ return *m == *requested_module;
+ }));
+
+ if (requested_module->status() == kInstantiating) {
+ module->set_dfs_ancestor_index(
+ std::min(module->dfs_ancestor_index(),
+ requested_module->dfs_ancestor_index()));
+ }
+ }
+
+ Handle<Script> script(module->script(), isolate);
+ Handle<ModuleInfo> module_info(module->info(), isolate);
+
+ // Resolve imports.
+ Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
+ for (int i = 0, n = regular_imports->length(); i < n; ++i) {
+ Handle<ModuleInfoEntry> entry(
+ ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
+ Handle<String> name(String::cast(entry->import_name()), isolate);
+ MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
+ ResolveSet resolve_set(zone);
+ Handle<Cell> cell;
+ if (!ResolveImport(module, name, entry->module_request(), loc, true,
+ &resolve_set)
+ .ToHandle(&cell)) {
+ return false;
+ }
+ module->regular_imports()->set(ImportIndex(entry->cell_index()), *cell);
+ }
+
+ // Resolve indirect exports.
+ Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
+ for (int i = 0, n = special_exports->length(); i < n; ++i) {
+ Handle<ModuleInfoEntry> entry(
+ ModuleInfoEntry::cast(special_exports->get(i)), isolate);
+ Handle<Object> name(entry->export_name(), isolate);
+ if (name->IsUndefined(isolate)) continue; // Star export.
+ MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
+ ResolveSet resolve_set(zone);
+ if (ResolveExport(module, Handle<String>::cast(name), loc, true,
+ &resolve_set)
+ .is_null()) {
+ return false;
+ }
+ }
+
+ MaybeTransitionComponent(module, stack, kInstantiated);
+ return true;
+}
+
+MaybeHandle<Object> Module::Evaluate(Handle<Module> module) {
+#ifdef DEBUG
+ if (FLAG_trace_module_status) {
+ OFStream os(stdout);
+ os << "Evaluating module ";
+ module->script()->GetNameOrSourceURL()->Print(os);
+#ifndef OBJECT_PRINT
+ os << "\n";
+#endif // OBJECT_PRINT
+ }
+#endif // DEBUG
+
+ Isolate* isolate = module->GetIsolate();
+ if (module->status() == kErrored) {
+ isolate->Throw(module->GetException());
+ return MaybeHandle<Object>();
+ }
+ DCHECK_NE(module->status(), kEvaluating);
+ DCHECK_GE(module->status(), kInstantiated);
+ Zone zone(isolate->allocator(), ZONE_NAME);
+
+ ZoneForwardList<Handle<Module>> stack(&zone);
+ unsigned dfs_index = 0;
+ Handle<Object> result;
+ if (!Evaluate(module, &stack, &dfs_index).ToHandle(&result)) {
+ for (auto& descendant : stack) {
+ DCHECK_EQ(descendant->status(), kEvaluating);
+ descendant->RecordError();
+ }
+ DCHECK_EQ(module->GetException(), isolate->pending_exception());
+ return MaybeHandle<Object>();
+ }
+ DCHECK_EQ(module->status(), kEvaluated);
+ DCHECK(stack.empty());
+ return result;
+}
+
+MaybeHandle<Object> Module::Evaluate(Handle<Module> module,
+ ZoneForwardList<Handle<Module>>* stack,
+ unsigned* dfs_index) {
+ Isolate* isolate = module->GetIsolate();
+ if (module->status() == kErrored) {
+ isolate->Throw(module->GetException());
+ return MaybeHandle<Object>();
+ }
+ if (module->status() >= kEvaluating) {
+ return isolate->factory()->undefined_value();
+ }
+ DCHECK_EQ(module->status(), kInstantiated);
+
+ Handle<JSGeneratorObject> generator(JSGeneratorObject::cast(module->code()),
+ isolate);
+ module->set_code(
+ generator->function()->shared()->scope_info()->ModuleDescriptorInfo());
+ module->SetStatus(kEvaluating);
+ module->set_dfs_index(*dfs_index);
+ module->set_dfs_ancestor_index(*dfs_index);
+ stack->push_front(module);
+ (*dfs_index)++;
+
+ // Recursion.
+ Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
+ for (int i = 0, length = requested_modules->length(); i < length; ++i) {
+ Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
+ isolate);
+ RETURN_ON_EXCEPTION(isolate, Evaluate(requested_module, stack, dfs_index),
+ Object);
+
+ DCHECK_GE(requested_module->status(), kEvaluating);
+ DCHECK_NE(requested_module->status(), kErrored);
+ SLOW_DCHECK(
+ // {requested_module} is evaluating iff it's on the {stack}.
+ (requested_module->status() == kEvaluating) ==
+ std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
+ return *m == *requested_module;
+ }));
+
+ if (requested_module->status() == kEvaluating) {
+ module->set_dfs_ancestor_index(
+ std::min(module->dfs_ancestor_index(),
+ requested_module->dfs_ancestor_index()));
+ }
+ }
+
+ // Evaluation of module body.
+ Handle<JSFunction> resume(
+ isolate->native_context()->generator_next_internal(), isolate);
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result, Execution::Call(isolate, resume, generator, 0, nullptr),
+ Object);
+ DCHECK(static_cast<JSIteratorResult*>(JSObject::cast(*result))
+ ->done()
+ ->BooleanValue());
+
+ MaybeTransitionComponent(module, stack, kEvaluated);
+ return handle(
+ static_cast<JSIteratorResult*>(JSObject::cast(*result))->value(),
+ isolate);
+}
+
+namespace {
+
+void FetchStarExports(Handle<Module> module, Zone* zone,
+ UnorderedModuleSet* visited) {
+ DCHECK_NE(module->status(), Module::kErrored);
+ DCHECK_GE(module->status(), Module::kInstantiating);
+
+ if (module->module_namespace()->IsJSModuleNamespace()) return; // Shortcut.
+
+ bool cycle = !visited->insert(module).second;
+ if (cycle) return;
+
+ Isolate* isolate = module->GetIsolate();
+ Handle<ObjectHashTable> exports(module->exports(), isolate);
+ UnorderedStringMap more_exports(zone);
+
+ // TODO(neis): Only allocate more_exports if there are star exports.
+ // Maybe split special_exports into indirect_exports and star_exports.
+
+ Handle<FixedArray> special_exports(module->info()->special_exports(),
+ isolate);
+ for (int i = 0, n = special_exports->length(); i < n; ++i) {
+ Handle<ModuleInfoEntry> entry(
+ ModuleInfoEntry::cast(special_exports->get(i)), isolate);
+ if (!entry->export_name()->IsUndefined(isolate)) {
+ continue; // Indirect export.
+ }
+
+ Handle<Module> requested_module(
+ Module::cast(module->requested_modules()->get(entry->module_request())),
+ isolate);
+
+ // Recurse.
+ FetchStarExports(requested_module, zone, visited);
+
+ // Collect all of [requested_module]'s exports that must be added to
+ // [module]'s exports (i.e. to [exports]). We record these in
+ // [more_exports]. Ambiguities (conflicting exports) are marked by mapping
+ // the name to undefined instead of a Cell.
+ Handle<ObjectHashTable> requested_exports(requested_module->exports(),
+ isolate);
+ for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
+ Object* key;
+ if (!requested_exports->ToKey(isolate, i, &key)) continue;
+ Handle<String> name(String::cast(key), isolate);
+
+ if (name->Equals(isolate->heap()->default_string())) continue;
+ if (!exports->Lookup(name)->IsTheHole(isolate)) continue;
+
+ Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
+ auto insert_result = more_exports.insert(std::make_pair(name, cell));
+ if (!insert_result.second) {
+ auto it = insert_result.first;
+ if (*it->second == *cell || it->second->IsUndefined(isolate)) {
+ // We already recorded this mapping before, or the name is already
+ // known to be ambiguous. In either case, there's nothing to do.
+ } else {
+ DCHECK(it->second->IsCell());
+ // Different star exports provide different cells for this name, hence
+ // mark the name as ambiguous.
+ it->second = isolate->factory()->undefined_value();
+ }
+ }
+ }
+ }
+
+ // Copy [more_exports] into [exports].
+ for (const auto& elem : more_exports) {
+ if (elem.second->IsUndefined(isolate)) continue; // Ambiguous export.
+ DCHECK(!elem.first->Equals(isolate->heap()->default_string()));
+ DCHECK(elem.second->IsCell());
+ exports = ObjectHashTable::Put(exports, elem.first, elem.second);
+ }
+ module->set_exports(*exports);
+}
+
+} // anonymous namespace
+
+Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module,
+ int module_request) {
+ Isolate* isolate = module->GetIsolate();
+ Handle<Module> requested_module(
+ Module::cast(module->requested_modules()->get(module_request)), isolate);
+ return Module::GetModuleNamespace(requested_module);
+}
+
+Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module) {
+ Isolate* isolate = module->GetIsolate();
+
+ Handle<HeapObject> object(module->module_namespace(), isolate);
+ if (!object->IsUndefined(isolate)) {
+ // Namespace object already exists.
+ return Handle<JSModuleNamespace>::cast(object);
+ }
+
+ // Collect the export names.
+ Zone zone(isolate->allocator(), ZONE_NAME);
+ UnorderedModuleSet visited(&zone);
+ FetchStarExports(module, &zone, &visited);
+ Handle<ObjectHashTable> exports(module->exports(), isolate);
+ ZoneVector<Handle<String>> names(&zone);
+ names.reserve(exports->NumberOfElements());
+ for (int i = 0, n = exports->Capacity(); i < n; ++i) {
+ Object* key;
+ if (!exports->ToKey(isolate, i, &key)) continue;
+ names.push_back(handle(String::cast(key), isolate));
+ }
+ DCHECK_EQ(static_cast<int>(names.size()), exports->NumberOfElements());
+
+ // Sort them alphabetically.
+ struct {
+ bool operator()(Handle<String> a, Handle<String> b) {
+ return String::Compare(a, b) == ComparisonResult::kLessThan;
+ }
+ } StringLess;
+ std::sort(names.begin(), names.end(), StringLess);
+
+ // Create the namespace object (initially empty).
+ Handle<JSModuleNamespace> ns = isolate->factory()->NewJSModuleNamespace();
+ ns->set_module(*module);
+ module->set_module_namespace(*ns);
+
+ // Create the properties in the namespace object.
+ PropertyAttributes attr = DONT_DELETE;
+ for (const auto& name : names) {
+ JSObject::SetAccessor(
+ ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr))
+ .Check();
+ }
+ JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked();
+
+ return ns;
+}
+
+MaybeHandle<Object> JSModuleNamespace::GetExport(Handle<String> name) {
+ Isolate* isolate = name->GetIsolate();
+
+ Handle<Object> object(module()->exports()->Lookup(name), isolate);
+ if (object->IsTheHole(isolate)) {
+ return isolate->factory()->undefined_value();
+ }
+
+ Handle<Object> value(Handle<Cell>::cast(object)->value(), isolate);
+ if (value->IsTheHole(isolate)) {
+ THROW_NEW_ERROR(
+ isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
+ }
+
+ return value;
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/src/objects/module.h b/deps/v8/src/objects/module.h
new file mode 100644
index 0000000000..ee59d97bd1
--- /dev/null
+++ b/deps/v8/src/objects/module.h
@@ -0,0 +1,329 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_OBJECTS_MODULE_H_
+#define V8_OBJECTS_MODULE_H_
+
+#include "src/objects.h"
+
+// Has to be the last include (doesn't have include guards):
+#include "src/objects/object-macros.h"
+
+namespace v8 {
+namespace internal {
+
+template <typename T>
+class Handle;
+class Isolate;
+class JSModuleNamespace;
+class ModuleDescriptor;
+class ModuleInfo;
+class ModuleInfoEntry;
+class String;
+class Zone;
+
+// A Module object is a mapping from export names to cells
+// This is still very much in flux.
+class Module : public Struct {
+ public:
+ DECL_CAST(Module)
+ DECL_VERIFIER(Module)
+ DECL_PRINTER(Module)
+
+ // The code representing this Module, or an abstraction thereof.
+ // This is either a SharedFunctionInfo or a JSFunction or a ModuleInfo
+ // depending on whether the module has been instantiated and evaluated. See
+ // Module::ModuleVerify() for the precise invariant.
+ DECL_ACCESSORS(code, Object)
+
+ // Arrays of cells corresponding to regular exports and regular imports.
+ // A cell's position in the array is determined by the cell index of the
+ // associated module entry (which coincides with the variable index of the
+ // associated variable).
+ DECL_ACCESSORS(regular_exports, FixedArray)
+ DECL_ACCESSORS(regular_imports, FixedArray)
+
+ // The complete export table, mapping an export name to its cell.
+ // TODO(neis): We may want to remove the regular exports from the table.
+ DECL_ACCESSORS(exports, ObjectHashTable)
+
+ // Hash for this object (a random non-zero Smi).
+ DECL_INT_ACCESSORS(hash)
+
+ // Status.
+ DECL_INT_ACCESSORS(status)
+ enum Status {
+ // Order matters!
+ kUninstantiated,
+ kPreInstantiating,
+ kInstantiating,
+ kInstantiated,
+ kEvaluating,
+ kEvaluated,
+ kErrored
+ };
+
+ // The exception in the case {status} is kErrored.
+ Object* GetException();
+
+ // The namespace object (or undefined).
+ DECL_ACCESSORS(module_namespace, HeapObject)
+
+ // Modules imported or re-exported by this module.
+ // Corresponds 1-to-1 to the module specifier strings in
+ // ModuleInfo::module_requests.
+ DECL_ACCESSORS(requested_modules, FixedArray)
+
+ // [script]: Script from which the module originates.
+ DECL_ACCESSORS(script, Script)
+
+ // Get the ModuleInfo associated with the code.
+ inline ModuleInfo* info() const;
+
+ // Implementation of spec operation ModuleDeclarationInstantiation.
+ // Returns false if an exception occurred during instantiation, true
+ // otherwise. (In the case where the callback throws an exception, that
+ // exception is propagated.)
+ static MUST_USE_RESULT bool Instantiate(Handle<Module> module,
+ v8::Local<v8::Context> context,
+ v8::Module::ResolveCallback callback);
+
+ // Implementation of spec operation ModuleEvaluation.
+ static MUST_USE_RESULT MaybeHandle<Object> Evaluate(Handle<Module> module);
+
+ Cell* GetCell(int cell_index);
+ static Handle<Object> LoadVariable(Handle<Module> module, int cell_index);
+ static void StoreVariable(Handle<Module> module, int cell_index,
+ Handle<Object> value);
+
+ // Get the namespace object for [module_request] of [module]. If it doesn't
+ // exist yet, it is created.
+ static Handle<JSModuleNamespace> GetModuleNamespace(Handle<Module> module,
+ int module_request);
+
+ // Get the namespace object for [module]. If it doesn't exist yet, it is
+ // created.
+ static Handle<JSModuleNamespace> GetModuleNamespace(Handle<Module> module);
+
+ static const int kCodeOffset = HeapObject::kHeaderSize;
+ static const int kExportsOffset = kCodeOffset + kPointerSize;
+ static const int kRegularExportsOffset = kExportsOffset + kPointerSize;
+ static const int kRegularImportsOffset = kRegularExportsOffset + kPointerSize;
+ static const int kHashOffset = kRegularImportsOffset + kPointerSize;
+ static const int kModuleNamespaceOffset = kHashOffset + kPointerSize;
+ static const int kRequestedModulesOffset =
+ kModuleNamespaceOffset + kPointerSize;
+ static const int kStatusOffset = kRequestedModulesOffset + kPointerSize;
+ static const int kDfsIndexOffset = kStatusOffset + kPointerSize;
+ static const int kDfsAncestorIndexOffset = kDfsIndexOffset + kPointerSize;
+ static const int kExceptionOffset = kDfsAncestorIndexOffset + kPointerSize;
+ static const int kScriptOffset = kExceptionOffset + kPointerSize;
+ static const int kSize = kScriptOffset + kPointerSize;
+
+ private:
+ friend class Factory;
+
+ DECL_ACCESSORS(exception, Object)
+
+ // TODO(neis): Don't store those in the module object?
+ DECL_INT_ACCESSORS(dfs_index)
+ DECL_INT_ACCESSORS(dfs_ancestor_index)
+
+ // Helpers for Instantiate and Evaluate.
+
+ static void CreateExport(Handle<Module> module, int cell_index,
+ Handle<FixedArray> names);
+ static void CreateIndirectExport(Handle<Module> module, Handle<String> name,
+ Handle<ModuleInfoEntry> entry);
+
+ // The [must_resolve] argument indicates whether or not an exception should be
+ // thrown in case the module does not provide an export named [name]
+ // (including when a cycle is detected). An exception is always thrown in the
+ // case of conflicting star exports.
+ //
+ // If [must_resolve] is true, a null result indicates an exception. If
+ // [must_resolve] is false, a null result may or may not indicate an
+ // exception (so check manually!).
+ class ResolveSet;
+ static MUST_USE_RESULT MaybeHandle<Cell> ResolveExport(
+ Handle<Module> module, Handle<String> name, MessageLocation loc,
+ bool must_resolve, ResolveSet* resolve_set);
+ static MUST_USE_RESULT MaybeHandle<Cell> ResolveImport(
+ Handle<Module> module, Handle<String> name, int module_request,
+ MessageLocation loc, bool must_resolve, ResolveSet* resolve_set);
+
+ static MUST_USE_RESULT MaybeHandle<Cell> ResolveExportUsingStarExports(
+ Handle<Module> module, Handle<String> name, MessageLocation loc,
+ bool must_resolve, ResolveSet* resolve_set);
+
+ static MUST_USE_RESULT bool PrepareInstantiate(
+ Handle<Module> module, v8::Local<v8::Context> context,
+ v8::Module::ResolveCallback callback);
+ static MUST_USE_RESULT bool FinishInstantiate(
+ Handle<Module> module, ZoneForwardList<Handle<Module>>* stack,
+ unsigned* dfs_index, Zone* zone);
+ static void RunInitializationCode(Handle<Module> module);
+
+ static MUST_USE_RESULT MaybeHandle<Object> Evaluate(
+ Handle<Module> module, ZoneForwardList<Handle<Module>>* stack,
+ unsigned* dfs_index);
+
+ static void MaybeTransitionComponent(Handle<Module> module,
+ ZoneForwardList<Handle<Module>>* stack,
+ Status new_status);
+
+ // To set status to kErrored, RecordError should be used.
+ void SetStatus(Status status);
+ void RecordError();
+
+#ifdef DEBUG
+ // For --trace-module-status.
+ void PrintStatusTransition(Status new_status);
+#endif // DEBUG
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Module);
+};
+
+// When importing a module namespace (import * as foo from "bar"), a
+// JSModuleNamespace object (representing module "bar") is created and bound to
+// the declared variable (foo). A module can have at most one namespace object.
+class JSModuleNamespace : public JSObject {
+ public:
+ DECL_CAST(JSModuleNamespace)
+ DECL_PRINTER(JSModuleNamespace)
+ DECL_VERIFIER(JSModuleNamespace)
+
+ // The actual module whose namespace is being represented.
+ DECL_ACCESSORS(module, Module)
+
+ // Retrieve the value exported by [module] under the given [name]. If there is
+ // no such export, return Just(undefined). If the export is uninitialized,
+ // schedule an exception and return Nothing.
+ MUST_USE_RESULT MaybeHandle<Object> GetExport(Handle<String> name);
+
+ // In-object fields.
+ enum {
+ kToStringTagFieldIndex,
+ kInObjectFieldCount,
+ };
+
+ static const int kModuleOffset = JSObject::kHeaderSize;
+ static const int kHeaderSize = kModuleOffset + kPointerSize;
+
+ static const int kSize = kHeaderSize + kPointerSize * kInObjectFieldCount;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSModuleNamespace);
+};
+
+// ModuleInfo is to ModuleDescriptor what ScopeInfo is to Scope.
+class ModuleInfo : public FixedArray {
+ public:
+ DECL_CAST(ModuleInfo)
+
+ static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone,
+ ModuleDescriptor* descr);
+
+ inline FixedArray* module_requests() const {
+ return FixedArray::cast(get(kModuleRequestsIndex));
+ }
+
+ inline FixedArray* special_exports() const {
+ return FixedArray::cast(get(kSpecialExportsIndex));
+ }
+
+ inline FixedArray* regular_exports() const {
+ return FixedArray::cast(get(kRegularExportsIndex));
+ }
+
+ inline FixedArray* regular_imports() const {
+ return FixedArray::cast(get(kRegularImportsIndex));
+ }
+
+ inline FixedArray* namespace_imports() const {
+ return FixedArray::cast(get(kNamespaceImportsIndex));
+ }
+
+ inline FixedArray* module_request_positions() const {
+ return FixedArray::cast(get(kModuleRequestPositionsIndex));
+ }
+
+ // Accessors for [regular_exports].
+ int RegularExportCount() const;
+ String* RegularExportLocalName(int i) const;
+ int RegularExportCellIndex(int i) const;
+ FixedArray* RegularExportExportNames(int i) const;
+
+#ifdef DEBUG
+ inline bool Equals(ModuleInfo* other) const {
+ return regular_exports() == other->regular_exports() &&
+ regular_imports() == other->regular_imports() &&
+ special_exports() == other->special_exports() &&
+ namespace_imports() == other->namespace_imports() &&
+ module_requests() == other->module_requests() &&
+ module_request_positions() == other->module_request_positions();
+ }
+#endif
+
+ private:
+ friend class Factory;
+ friend class ModuleDescriptor;
+ enum {
+ kModuleRequestsIndex,
+ kSpecialExportsIndex,
+ kRegularExportsIndex,
+ kNamespaceImportsIndex,
+ kRegularImportsIndex,
+ kModuleRequestPositionsIndex,
+ kLength
+ };
+ enum {
+ kRegularExportLocalNameOffset,
+ kRegularExportCellIndexOffset,
+ kRegularExportExportNamesOffset,
+ kRegularExportLength
+ };
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfo);
+};
+
+class ModuleInfoEntry : public Struct {
+ public:
+ DECL_CAST(ModuleInfoEntry)
+ DECL_PRINTER(ModuleInfoEntry)
+ DECL_VERIFIER(ModuleInfoEntry)
+
+ DECL_ACCESSORS(export_name, Object)
+ DECL_ACCESSORS(local_name, Object)
+ DECL_ACCESSORS(import_name, Object)
+ DECL_INT_ACCESSORS(module_request)
+ DECL_INT_ACCESSORS(cell_index)
+ DECL_INT_ACCESSORS(beg_pos)
+ DECL_INT_ACCESSORS(end_pos)
+
+ static Handle<ModuleInfoEntry> New(Isolate* isolate,
+ Handle<Object> export_name,
+ Handle<Object> local_name,
+ Handle<Object> import_name,
+ int module_request, int cell_index,
+ int beg_pos, int end_pos);
+
+ static const int kExportNameOffset = HeapObject::kHeaderSize;
+ static const int kLocalNameOffset = kExportNameOffset + kPointerSize;
+ static const int kImportNameOffset = kLocalNameOffset + kPointerSize;
+ static const int kModuleRequestOffset = kImportNameOffset + kPointerSize;
+ static const int kCellIndexOffset = kModuleRequestOffset + kPointerSize;
+ static const int kBegPosOffset = kCellIndexOffset + kPointerSize;
+ static const int kEndPosOffset = kBegPosOffset + kPointerSize;
+ static const int kSize = kEndPosOffset + kPointerSize;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfoEntry);
+};
+
+} // namespace internal
+} // namespace v8
+
+#include "src/objects/object-macros-undef.h"
+
+#endif // V8_OBJECTS_MODULE_H_
diff --git a/deps/v8/src/objects/name-inl.h b/deps/v8/src/objects/name-inl.h
index 4271a1da14..389427cd0d 100644
--- a/deps/v8/src/objects/name-inl.h
+++ b/deps/v8/src/objects/name-inl.h
@@ -21,6 +21,7 @@ SMI_ACCESSORS(Symbol, flags, kFlagsOffset)
BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
BOOL_ACCESSORS(Symbol, flags, is_well_known_symbol, kWellKnownSymbolBit)
BOOL_ACCESSORS(Symbol, flags, is_public, kPublicBit)
+BOOL_ACCESSORS(Symbol, flags, is_interesting_symbol, kInterestingSymbolBit)
TYPE_CHECKER(Symbol, SYMBOL_TYPE)
@@ -78,6 +79,10 @@ uint32_t Name::Hash() {
return String::cast(this)->ComputeAndSetHash();
}
+bool Name::IsInterestingSymbol() const {
+ return IsSymbol() && Symbol::cast(this)->is_interesting_symbol();
+}
+
bool Name::IsPrivate() {
return this->IsSymbol() && Symbol::cast(this)->is_private();
}
diff --git a/deps/v8/src/objects/name.h b/deps/v8/src/objects/name.h
index 1f35cac865..ede1d14fb0 100644
--- a/deps/v8/src/objects/name.h
+++ b/deps/v8/src/objects/name.h
@@ -34,6 +34,13 @@ class Name : public HeapObject {
// Conversion.
inline bool AsArrayIndex(uint32_t* index);
+ // An "interesting symbol" is a well-known symbol, like @@toStringTag,
+ // that's often looked up on random objects but is usually not present.
+ // We optimize this by setting a flag on the object's map when such
+ // symbol properties are added, so we can optimize lookups on objects
+ // that don't have the flag.
+ inline bool IsInterestingSymbol() const;
+
// If the name is private, it can only name own properties.
inline bool IsPrivate();
@@ -145,6 +152,12 @@ class Symbol : public Name {
// a load.
DECL_BOOLEAN_ACCESSORS(is_well_known_symbol)
+ // [is_interesting_symbol]: Whether this is an "interesting symbol", which
+ // is a well-known symbol like @@toStringTag that's often looked up on
+ // random objects but is usually not present. See Name::IsInterestingSymbol()
+ // for a detailed description.
+ DECL_BOOLEAN_ACCESSORS(is_interesting_symbol)
+
// [is_public]: Whether this is a symbol created by Symbol.for. Calling
// Symbol.keyFor on such a symbol simply needs to return the attached name.
DECL_BOOLEAN_ACCESSORS(is_public)
@@ -164,6 +177,7 @@ class Symbol : public Name {
static const int kPrivateBit = 0;
static const int kWellKnownSymbolBit = 1;
static const int kPublicBit = 2;
+ static const int kInterestingSymbolBit = 3;
typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor;
// No weak fields.
diff --git a/deps/v8/src/objects/object-macros-undef.h b/deps/v8/src/objects/object-macros-undef.h
index 6d5f10c07d..4ad2cd2f71 100644
--- a/deps/v8/src/objects/object-macros-undef.h
+++ b/deps/v8/src/objects/object-macros-undef.h
@@ -34,6 +34,8 @@
#undef WRITE_INT_FIELD
#undef READ_INTPTR_FIELD
#undef WRITE_INTPTR_FIELD
+#undef RELAXED_READ_INTPTR_FIELD
+#undef RELAXED_WRITE_INTPTR_FIELD
#undef READ_UINT8_FIELD
#undef WRITE_UINT8_FIELD
#undef READ_INT8_FIELD
diff --git a/deps/v8/src/objects/object-macros.h b/deps/v8/src/objects/object-macros.h
index e672af14c9..eb192bcd8c 100644
--- a/deps/v8/src/objects/object-macros.h
+++ b/deps/v8/src/objects/object-macros.h
@@ -20,6 +20,10 @@
inline int name() const; \
inline void set_##name(int value);
+#define DECL_INT32_ACCESSORS(name) \
+ inline int32_t name() const; \
+ inline void set_##name(int32_t value);
+
#define DECL_ACCESSORS(name, type) \
inline type* name() const; \
inline void set_##name(type* value, \
@@ -43,6 +47,12 @@
int holder::name() const { return READ_INT_FIELD(this, offset); } \
void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
+#define INT32_ACCESSORS(holder, name, offset) \
+ int32_t holder::name() const { return READ_INT32_FIELD(this, offset); } \
+ void holder::set_##name(int32_t value) { \
+ WRITE_INT32_FIELD(this, offset, value); \
+ }
+
#define ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \
set_condition) \
type* holder::name() const { \
@@ -155,15 +165,15 @@
#define WRITE_BARRIER(heap, object, offset, value) \
heap->incremental_marking()->RecordWrite( \
object, HeapObject::RawField(object, offset), value); \
- heap->RecordWrite(object, offset, value);
-
-#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
- if (mode != SKIP_WRITE_BARRIER) { \
- if (mode == UPDATE_WRITE_BARRIER) { \
- heap->incremental_marking()->RecordWrite( \
- object, HeapObject::RawField(object, offset), value); \
- } \
- heap->RecordWrite(object, offset, value); \
+ heap->RecordWrite(object, HeapObject::RawField(object, offset), value);
+
+#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
+ if (mode != SKIP_WRITE_BARRIER) { \
+ if (mode == UPDATE_WRITE_BARRIER) { \
+ heap->incremental_marking()->RecordWrite( \
+ object, HeapObject::RawField(object, offset), value); \
+ } \
+ heap->RecordWrite(object, HeapObject::RawField(object, offset), value); \
}
#define READ_DOUBLE_FIELD(p, offset) \
@@ -178,6 +188,10 @@
#define WRITE_INT_FIELD(p, offset, value) \
(*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
+#define RELAXED_READ_INTPTR_FIELD(p, offset) \
+ static_cast<intptr_t>(base::Relaxed_Load( \
+ reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
+
#define READ_INTPTR_FIELD(p, offset) \
(*reinterpret_cast<const intptr_t*>(FIELD_ADDR_CONST(p, offset)))
@@ -195,9 +209,17 @@
#define WRITE_UINT8_FIELD(p, offset, value) \
(*reinterpret_cast<uint8_t*>(FIELD_ADDR(p, offset)) = value)
+#define RELAXED_WRITE_INT8_FIELD(p, offset, value) \
+ base::Relaxed_Store(reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
+ static_cast<base::Atomic8>(value));
+
#define READ_INT8_FIELD(p, offset) \
(*reinterpret_cast<const int8_t*>(FIELD_ADDR_CONST(p, offset)))
+#define RELAXED_READ_INT8_FIELD(p, offset) \
+ static_cast<int8_t>(base::Relaxed_Load( \
+ reinterpret_cast<const base::Atomic8*>(FIELD_ADDR_CONST(p, offset))))
+
#define WRITE_INT8_FIELD(p, offset, value) \
(*reinterpret_cast<int8_t*>(FIELD_ADDR(p, offset)) = value)
diff --git a/deps/v8/src/objects/scope-info.cc b/deps/v8/src/objects/scope-info.cc
index 9a30b710d7..87045d044e 100644
--- a/deps/v8/src/objects/scope-info.cc
+++ b/deps/v8/src/objects/scope-info.cc
@@ -144,29 +144,28 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
bool has_simple_parameters = false;
bool asm_module = false;
- bool asm_function = false;
+ bool calls_sloppy_eval = false;
if (scope->is_function_scope()) {
DeclarationScope* function_scope = scope->AsDeclarationScope();
has_simple_parameters = function_scope->has_simple_parameters();
asm_module = function_scope->asm_module();
- asm_function = function_scope->asm_function();
}
FunctionKind function_kind = kNormalFunction;
if (scope->is_declaration_scope()) {
function_kind = scope->AsDeclarationScope()->function_kind();
+ calls_sloppy_eval = scope->AsDeclarationScope()->calls_sloppy_eval();
}
// Encode the flags.
int flags =
ScopeTypeField::encode(scope->scope_type()) |
- CallsEvalField::encode(scope->calls_eval()) |
+ CallsSloppyEvalField::encode(calls_sloppy_eval) |
LanguageModeField::encode(scope->language_mode()) |
DeclarationScopeField::encode(scope->is_declaration_scope()) |
ReceiverVariableField::encode(receiver_info) |
HasNewTargetField::encode(has_new_target) |
FunctionVariableField::encode(function_name_info) |
AsmModuleField::encode(asm_module) |
- AsmFunctionField::encode(asm_function) |
HasSimpleParametersField::encode(has_simple_parameters) |
FunctionKindField::encode(function_kind) |
HasOuterScopeInfoField::encode(has_outer_scope_info) |
@@ -299,11 +298,11 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
// Encode the flags.
int flags =
- ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) |
+ ScopeTypeField::encode(WITH_SCOPE) | CallsSloppyEvalField::encode(false) |
LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) |
ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
- AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) |
+ HasSimpleParametersField::encode(true) |
FunctionKindField::encode(kNormalFunction) |
HasOuterScopeInfoField::encode(has_outer_scope_info) |
IsDebugEvaluateScopeField::encode(false);
@@ -351,16 +350,17 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
// Encode the flags.
- int flags =
- ScopeTypeField::encode(SCRIPT_SCOPE) | CallsEvalField::encode(false) |
- LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(true) |
- ReceiverVariableField::encode(receiver_info) |
- FunctionVariableField::encode(function_name_info) |
- AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
- HasSimpleParametersField::encode(has_simple_parameters) |
- FunctionKindField::encode(FunctionKind::kNormalFunction) |
- HasOuterScopeInfoField::encode(has_outer_scope_info) |
- IsDebugEvaluateScopeField::encode(false);
+ int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
+ CallsSloppyEvalField::encode(false) |
+ LanguageModeField::encode(SLOPPY) |
+ DeclarationScopeField::encode(true) |
+ ReceiverVariableField::encode(receiver_info) |
+ FunctionVariableField::encode(function_name_info) |
+ AsmModuleField::encode(false) |
+ HasSimpleParametersField::encode(has_simple_parameters) |
+ FunctionKindField::encode(FunctionKind::kNormalFunction) |
+ HasOuterScopeInfoField::encode(has_outer_scope_info) |
+ IsDebugEvaluateScopeField::encode(false);
scope_info->SetFlags(flags);
scope_info->SetParameterCount(parameter_count);
scope_info->SetStackLocalCount(stack_local_count);
@@ -404,8 +404,12 @@ ScopeType ScopeInfo::scope_type() {
return ScopeTypeField::decode(Flags());
}
-bool ScopeInfo::CallsEval() {
- return length() > 0 && CallsEvalField::decode(Flags());
+bool ScopeInfo::CallsSloppyEval() {
+ bool calls_sloppy_eval =
+ length() > 0 && CallsSloppyEvalField::decode(Flags());
+ DCHECK_IMPLIES(calls_sloppy_eval, is_sloppy(language_mode()));
+ DCHECK_IMPLIES(calls_sloppy_eval, is_declaration_scope());
+ return calls_sloppy_eval;
}
LanguageMode ScopeInfo::language_mode() {
diff --git a/deps/v8/src/objects/scope-info.h b/deps/v8/src/objects/scope-info.h
index e60ac99162..db8bd3a5a8 100644
--- a/deps/v8/src/objects/scope-info.h
+++ b/deps/v8/src/objects/scope-info.h
@@ -20,6 +20,7 @@ class Handle;
class Isolate;
template <typename T>
class MaybeHandle;
+class ModuleInfo;
class Scope;
class Zone;
@@ -37,9 +38,6 @@ class ScopeInfo : public FixedArray {
// Return the type of this scope.
ScopeType scope_type();
- // Does this scope call eval?
- bool CallsEval();
-
// Return the language mode of this scope.
LanguageMode language_mode();
@@ -47,7 +45,7 @@ class ScopeInfo : public FixedArray {
bool is_declaration_scope();
// Does this scope make a sloppy eval call?
- bool CallsSloppyEval() { return CallsEval() && is_sloppy(language_mode()); }
+ bool CallsSloppyEval();
// Return the total number of locals allocated on the stack and in the
// context. This includes the parameters that are allocated in the context.
@@ -87,9 +85,6 @@ class ScopeInfo : public FixedArray {
// Return if this is a function scope with "use asm".
inline bool IsAsmModule() { return AsmModuleField::decode(Flags()); }
- // Return if this is a nested function within an asm module scope.
- inline bool IsAsmFunction() { return AsmFunctionField::decode(Flags()); }
-
inline bool HasSimpleParameters() {
return HasSimpleParametersField::decode(Flags());
}
@@ -301,10 +296,11 @@ class ScopeInfo : public FixedArray {
// Properties of scopes.
class ScopeTypeField : public BitField<ScopeType, 0, 4> {};
- class CallsEvalField : public BitField<bool, ScopeTypeField::kNext, 1> {};
+ class CallsSloppyEvalField : public BitField<bool, ScopeTypeField::kNext, 1> {
+ };
STATIC_ASSERT(LANGUAGE_END == 2);
class LanguageModeField
- : public BitField<LanguageMode, CallsEvalField::kNext, 1> {};
+ : public BitField<LanguageMode, CallsSloppyEvalField::kNext, 1> {};
class DeclarationScopeField
: public BitField<bool, LanguageModeField::kNext, 1> {};
class ReceiverVariableField
@@ -316,9 +312,8 @@ class ScopeInfo : public FixedArray {
: public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {};
class AsmModuleField
: public BitField<bool, FunctionVariableField::kNext, 1> {};
- class AsmFunctionField : public BitField<bool, AsmModuleField::kNext, 1> {};
class HasSimpleParametersField
- : public BitField<bool, AsmFunctionField::kNext, 1> {};
+ : public BitField<bool, AsmModuleField::kNext, 1> {};
class FunctionKindField
: public BitField<FunctionKind, HasSimpleParametersField::kNext, 10> {};
class HasOuterScopeInfoField
diff --git a/deps/v8/src/objects/shared-function-info-inl.h b/deps/v8/src/objects/shared-function-info-inl.h
index 028d3cf086..d9e0407617 100644
--- a/deps/v8/src/objects/shared-function-info-inl.h
+++ b/deps/v8/src/objects/shared-function-info-inl.h
@@ -6,6 +6,7 @@
#define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
#include "src/heap/heap-inl.h"
+#include "src/objects/scope-info.h"
#include "src/objects/shared-function-info.h"
// Has to be the last include (doesn't have include guards):
@@ -57,11 +58,6 @@ INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
INT_ACCESSORS(SharedFunctionInfo, function_token_position,
kFunctionTokenPositionOffset)
INT_ACCESSORS(SharedFunctionInfo, compiler_hints, kCompilerHintsOffset)
-INT_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
- kOptCountAndBailoutReasonOffset)
-INT_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
-INT_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
-INT_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
bool SharedFunctionInfo::has_shared_name() const {
return raw_name() != kNoSharedNameSentinel;
@@ -93,8 +89,6 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, compiler_hints, uses_arguments,
BIT_FIELD_ACCESSORS(SharedFunctionInfo, compiler_hints,
has_duplicate_parameters,
SharedFunctionInfo::HasDuplicateParametersBit)
-BIT_FIELD_ACCESSORS(SharedFunctionInfo, compiler_hints, asm_function,
- SharedFunctionInfo::IsAsmFunctionBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, compiler_hints, is_declaration,
SharedFunctionInfo::IsDeclarationBit)
@@ -104,8 +98,14 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, compiler_hints, force_inline,
SharedFunctionInfo::ForceInlineBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, compiler_hints, is_asm_wasm_broken,
SharedFunctionInfo::IsAsmWasmBrokenBit)
-BIT_FIELD_ACCESSORS(SharedFunctionInfo, compiler_hints, optimization_disabled,
- SharedFunctionInfo::OptimizationDisabledBit)
+
+bool SharedFunctionInfo::optimization_disabled() const {
+ return disable_optimization_reason() != BailoutReason::kNoReason;
+}
+
+BailoutReason SharedFunctionInfo::disable_optimization_reason() const {
+ return DisabledOptimizationReasonBits::decode(compiler_hints());
+}
LanguageMode SharedFunctionInfo::language_mode() {
STATIC_ASSERT(LANGUAGE_END == 2);
@@ -163,6 +163,10 @@ void SharedFunctionInfo::set_function_map_index(int index) {
set_compiler_hints(FunctionMapIndexBits::update(compiler_hints(), index));
}
+void SharedFunctionInfo::clear_padding() {
+ memset(this->address() + kSize, 0, kAlignedSize - kSize);
+}
+
void SharedFunctionInfo::UpdateFunctionMapIndex() {
int map_index = Context::FunctionMapIndex(
language_mode(), kind(), has_shared_name(), needs_home_object());
@@ -269,11 +273,6 @@ bool SharedFunctionInfo::HasDebugInfo() const {
return has_debug_info;
}
-bool SharedFunctionInfo::HasDebugCode() const {
- if (HasBaselineCode()) return code()->has_debug_break_slots();
- return HasBytecodeArray();
-}
-
bool SharedFunctionInfo::IsApiFunction() {
return function_data()->IsFunctionTemplateInfo();
}
@@ -357,42 +356,6 @@ void SharedFunctionInfo::set_inferred_name(String* inferred_name) {
set_function_identifier(inferred_name);
}
-BIT_FIELD_ACCESSORS(SharedFunctionInfo, counters, ic_age,
- SharedFunctionInfo::ICAgeBits)
-
-BIT_FIELD_ACCESSORS(SharedFunctionInfo, counters, deopt_count,
- SharedFunctionInfo::DeoptCountBits)
-
-void SharedFunctionInfo::increment_deopt_count() {
- int value = counters();
- int deopt_count = DeoptCountBits::decode(value);
- // Saturate the deopt count when incrementing, rather than overflowing.
- if (deopt_count < DeoptCountBits::kMax) {
- set_counters(DeoptCountBits::update(value, deopt_count + 1));
- }
-}
-
-BIT_FIELD_ACCESSORS(SharedFunctionInfo, counters, opt_reenable_tries,
- SharedFunctionInfo::OptReenableTriesBits)
-
-BIT_FIELD_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason, opt_count,
- SharedFunctionInfo::OptCountBits)
-
-BIT_FIELD_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
- disable_optimization_reason,
- SharedFunctionInfo::DisabledOptimizationReasonBits)
-
-void SharedFunctionInfo::TryReenableOptimization() {
- int tries = opt_reenable_tries();
- set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax);
- // We reenable optimization whenever the number of tries is a large
- // enough power of 2.
- if (tries >= 16 && (((tries - 1) & tries) == 0)) {
- set_optimization_disabled(false);
- set_deopt_count(0);
- }
-}
-
bool SharedFunctionInfo::IsUserJavaScript() {
Object* script_obj = script();
if (script_obj->IsUndefined(GetIsolate())) return false;
diff --git a/deps/v8/src/objects/shared-function-info.h b/deps/v8/src/objects/shared-function-info.h
index 03cae0aede..6676c619a6 100644
--- a/deps/v8/src/objects/shared-function-info.h
+++ b/deps/v8/src/objects/shared-function-info.h
@@ -201,9 +201,6 @@ class SharedFunctionInfo : public HeapObject {
bool HasCoverageInfo() const;
CoverageInfo* GetCoverageInfo() const;
- // A function has debug code if the compiled code has debug break slots.
- inline bool HasDebugCode() const;
-
// [debug info]: Debug information.
DECL_ACCESSORS(debug_info, Object)
@@ -253,7 +250,7 @@ class SharedFunctionInfo : public HeapObject {
// The function cannot cause any side effects.
bool HasNoSideEffect();
- // Used for flags such as --hydrogen-filter.
+ // Used for flags such as --turbo-filter.
bool PassesFilter(const char* raw_filter);
// Position of the 'function' token in the script source.
@@ -278,23 +275,9 @@ class SharedFunctionInfo : public HeapObject {
// drive optimization.
DECL_INT_ACCESSORS(compiler_hints)
- DECL_INT_ACCESSORS(ast_node_count)
-
- DECL_INT_ACCESSORS(profiler_ticks)
-
- // Inline cache age is used to infer whether the function survived a context
- // disposal or not. In the former case we reset the opt_count.
- DECL_INT_ACCESSORS(ic_age)
-
// Indicates if this function can be lazy compiled.
DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
- // Indicates whether optimizations have been disabled for this
- // shared function info. If a function is repeatedly optimized or if
- // we cannot optimize the function we disable optimization to avoid
- // spending time attempting to optimize it again.
- DECL_BOOLEAN_ACCESSORS(optimization_disabled)
-
// Indicates the language mode.
inline LanguageMode language_mode();
inline void set_language_mode(LanguageMode language_mode);
@@ -314,9 +297,6 @@ class SharedFunctionInfo : public HeapObject {
// Indicate that this function should always be inlined in optimized code.
DECL_BOOLEAN_ACCESSORS(force_inline)
- // Indicates that this function is an asm function.
- DECL_BOOLEAN_ACCESSORS(asm_function)
-
// Whether this function was created from a FunctionDeclaration.
DECL_BOOLEAN_ACCESSORS(is_declaration)
@@ -329,9 +309,21 @@ class SharedFunctionInfo : public HeapObject {
// this shared function info.
DECL_INT_ACCESSORS(function_map_index)
+ // Clear uninitialized padding space. This ensures that the snapshot content
+ // is deterministic.
+ inline void clear_padding();
+
// Recalculates the |map_index| value after modifications of this shared info.
inline void UpdateFunctionMapIndex();
+ // Indicates whether optimizations have been disabled for this shared function
+ // info. If we cannot optimize the function we disable optimization to avoid
+ // spending time attempting to optimize it again.
+ inline bool optimization_disabled() const;
+
+ // The reason why optimization was disabled.
+ inline BailoutReason disable_optimization_reason() const;
+
// Disable (further) attempted optimization of all functions sharing this
// shared function info.
void DisableOptimization(BailoutReason reason);
@@ -341,29 +333,6 @@ class SharedFunctionInfo : public HeapObject {
Handle<Object> GetSourceCode();
Handle<Object> GetSourceCodeHarmony();
- // Number of times the function was optimized.
- DECL_INT_ACCESSORS(opt_count)
-
- // Number of times the function was deoptimized.
- DECL_INT_ACCESSORS(deopt_count)
- inline void increment_deopt_count();
-
- // Number of time we tried to re-enable optimization after it
- // was disabled due to high number of deoptimizations.
- DECL_INT_ACCESSORS(opt_reenable_tries)
-
- inline void TryReenableOptimization();
-
- // Stores deopt_count, opt_reenable_tries and ic_age as bit-fields.
- inline void set_counters(int value);
- inline int counters() const;
-
- // Stores opt_count and bailout_reason as bit-fields.
- DECL_INT_ACCESSORS(opt_count_and_bailout_reason)
-
- inline BailoutReason disable_optimization_reason() const;
- inline void set_disable_optimization_reason(BailoutReason reason);
-
// Tells whether this function should be subject to debugging.
inline bool IsSubjectToDebugging();
@@ -391,8 +360,9 @@ class SharedFunctionInfo : public HeapObject {
// Dispatched behavior.
DECL_PRINTER(SharedFunctionInfo)
DECL_VERIFIER(SharedFunctionInfo)
-
- void ResetForNewContext(int new_ic_age);
+#ifdef OBJECT_PRINT
+ void PrintSourceCode(std::ostream& os);
+#endif
// Iterate over all shared function infos in a given script.
class ScriptIterator {
@@ -438,36 +408,32 @@ class SharedFunctionInfo : public HeapObject {
#endif
// Layout description.
-#define SHARED_FUNCTION_INFO_FIELDS(V) \
- /* Pointer fields. */ \
- V(kCodeOffset, kPointerSize) \
- V(kNameOffset, kPointerSize) \
- V(kScopeInfoOffset, kPointerSize) \
- V(kOuterScopeInfoOffset, kPointerSize) \
- V(kConstructStubOffset, kPointerSize) \
- V(kInstanceClassNameOffset, kPointerSize) \
- V(kFunctionDataOffset, kPointerSize) \
- V(kScriptOffset, kPointerSize) \
- V(kDebugInfoOffset, kPointerSize) \
- V(kFunctionIdentifierOffset, kPointerSize) \
- V(kFeedbackMetadataOffset, kPointerSize) \
- V(kPreParsedScopeDataOffset, kPointerSize) \
- V(kEndOfPointerFieldsOffset, 0) \
- /* Raw data fields. */ \
- V(kFunctionLiteralIdOffset, kInt32Size) \
- V(kUniqueIdOffset, kUniqueIdFieldSize) \
- V(kLengthOffset, kInt32Size) \
- V(kFormalParameterCountOffset, kInt32Size) \
- V(kExpectedNofPropertiesOffset, kInt32Size) \
- V(kStartPositionAndTypeOffset, kInt32Size) \
- V(kEndPositionOffset, kInt32Size) \
- V(kFunctionTokenPositionOffset, kInt32Size) \
- V(kCompilerHintsOffset, kInt32Size) \
- V(kOptCountAndBailoutReasonOffset, kInt32Size) \
- V(kCountersOffset, kInt32Size) \
- V(kAstNodeCountOffset, kInt32Size) \
- V(kProfilerTicksOffset, kInt32Size) \
- /* Total size. */ \
+#define SHARED_FUNCTION_INFO_FIELDS(V) \
+ /* Pointer fields. */ \
+ V(kCodeOffset, kPointerSize) \
+ V(kNameOffset, kPointerSize) \
+ V(kScopeInfoOffset, kPointerSize) \
+ V(kOuterScopeInfoOffset, kPointerSize) \
+ V(kConstructStubOffset, kPointerSize) \
+ V(kInstanceClassNameOffset, kPointerSize) \
+ V(kFunctionDataOffset, kPointerSize) \
+ V(kScriptOffset, kPointerSize) \
+ V(kDebugInfoOffset, kPointerSize) \
+ V(kFunctionIdentifierOffset, kPointerSize) \
+ V(kFeedbackMetadataOffset, kPointerSize) \
+ V(kPreParsedScopeDataOffset, kPointerSize) \
+ V(kEndOfPointerFieldsOffset, 0) \
+ /* Raw data fields. */ \
+ V(kFunctionLiteralIdOffset, kInt32Size) \
+ V(kUniqueIdOffset, kUniqueIdFieldSize) \
+ V(kLengthOffset, kInt32Size) \
+ V(kFormalParameterCountOffset, kInt32Size) \
+ V(kExpectedNofPropertiesOffset, kInt32Size) \
+ V(kStartPositionAndTypeOffset, kInt32Size) \
+ V(kEndPositionOffset, kInt32Size) \
+ V(kFunctionTokenPositionOffset, kInt32Size) \
+ V(kCompilerHintsOffset, kInt32Size) \
+ /* Total size. */ \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
@@ -496,19 +462,20 @@ class SharedFunctionInfo : public HeapObject {
V(FunctionKindBits, FunctionKind, 10, _) \
V(HasDuplicateParametersBit, bool, 1, _) \
V(AllowLazyCompilationBit, bool, 1, _) \
- V(OptimizationDisabledBit, bool, 1, _) \
V(UsesArgumentsBit, bool, 1, _) \
V(NeedsHomeObjectBit, bool, 1, _) \
V(ForceInlineBit, bool, 1, _) \
- V(IsAsmFunctionBit, bool, 1, _) \
V(IsDeclarationBit, bool, 1, _) \
V(IsAsmWasmBrokenBit, bool, 1, _) \
V(FunctionMapIndexBits, int, 5, _) \
- /* Bits 26-31 are unused. */
+ V(DisabledOptimizationReasonBits, BailoutReason, 7, _)
DEFINE_BIT_FIELDS(COMPILER_HINTS_BIT_FIELDS)
#undef COMPILER_HINTS_BIT_FIELDS
+ // Bailout reasons must fit in the DisabledOptimizationReason bitfield.
+ STATIC_ASSERT(kLastErrorMessage <= DisabledOptimizationReasonBits::kMax);
+
// Masks for checking if certain FunctionKind bits are set without fully
// decoding of the FunctionKind bit field.
static const int kClassConstructorMask = FunctionKind::kClassConstructor
@@ -530,23 +497,6 @@ class SharedFunctionInfo : public HeapObject {
DEFINE_BIT_FIELDS(DEBUGGER_HINTS_BIT_FIELDS)
#undef DEBUGGER_HINTS_BIT_FIELDS
-// Bit fields in |counters|.
-#define COUNTERS_BIT_FIELDS(V, _) \
- V(DeoptCountBits, int, 4, _) \
- V(OptReenableTriesBits, int, 18, _) \
- V(ICAgeBits, int, 8, _)
-
- DEFINE_BIT_FIELDS(COUNTERS_BIT_FIELDS)
-#undef COUNTERS_BIT_FIELDS
-
-// Bit fields in |opt_count_and_bailout_reason|.
-#define OPT_COUNT_AND_BAILOUT_REASON_BIT_FIELDS(V, _) \
- V(OptCountBits, int, 22, _) \
- V(DisabledOptimizationReasonBits, BailoutReason, 8, _)
-
- DEFINE_BIT_FIELDS(OPT_COUNT_AND_BAILOUT_REASON_BIT_FIELDS)
-#undef OPT_COUNT_AND_BAILOUT_REASON_BIT_FIELDS
-
private:
// [raw_name]: Function name string or kNoSharedNameSentinel.
DECL_ACCESSORS(raw_name, Object)
diff --git a/deps/v8/src/objects/string-inl.h b/deps/v8/src/objects/string-inl.h
index c83ecffa46..a30b65da95 100644
--- a/deps/v8/src/objects/string-inl.h
+++ b/deps/v8/src/objects/string-inl.h
@@ -8,6 +8,7 @@
#include "src/objects/string.h"
#include "src/conversions-inl.h"
+#include "src/factory.h"
#include "src/objects/name-inl.h"
#include "src/string-hasher-inl.h"
@@ -514,7 +515,7 @@ String* ConsString::second() {
}
Object* ConsString::unchecked_second() {
- return READ_FIELD(this, kSecondOffset);
+ return RELAXED_READ_FIELD(this, kSecondOffset);
}
void ConsString::set_second(String* value, WriteBarrierMode mode) {
diff --git a/deps/v8/src/objects/string.h b/deps/v8/src/objects/string.h
index 04dbe9bbb7..1a9baa61b7 100644
--- a/deps/v8/src/objects/string.h
+++ b/deps/v8/src/objects/string.h
@@ -345,7 +345,14 @@ class String : public Name {
static const uc32 kMaxCodePoint = 0x10ffff;
// Maximal string length.
- static const int kMaxLength = (1 << 28) - 16;
+ // The max length is different on 32 and 64 bit platforms. Max length for a
+ // 32-bit platform is ~268.4M chars. On 64-bit platforms, max length is
+ // ~1.073B chars. The limit on 64-bit is so that SeqTwoByteString::kMaxSize
+ // can fit in a 32bit int: 2^31 - 1 is the max positive int, minus one bit as
+ // each char needs two bytes, subtract 24 bytes for the string header size.
+
+ // See include/v8.h for the definition.
+ static const int kMaxLength = v8::String::kMaxLength;
// Max length for computing hash. For strings longer than this limit the
// string length is used as the hash value.
@@ -489,6 +496,10 @@ class SeqOneByteString : public SeqString {
inline uint8_t* GetChars();
+ // Clear uninitialized padding space. This ensures that the snapshot content
+ // is deterministic.
+ void clear_padding();
+
DECL_CAST(SeqOneByteString)
// Garbage collection support. This method is called by the
@@ -502,7 +513,7 @@ class SeqOneByteString : public SeqString {
}
// Maximal memory usage for a single sequential one-byte string.
- static const int kMaxSize = 512 * MB - 1;
+ static const int kMaxSize = OBJECT_POINTER_ALIGN(kMaxLength + kHeaderSize);
STATIC_ASSERT((kMaxSize - kHeaderSize) >= String::kMaxLength);
class BodyDescriptor;
@@ -528,6 +539,10 @@ class SeqTwoByteString : public SeqString {
inline uc16* GetChars();
+ // Clear uninitialized padding space. This ensures that the snapshot content
+ // is deterministic.
+ void clear_padding();
+
// For regexp code.
const uint16_t* SeqTwoByteStringGetData(unsigned start);
@@ -544,7 +559,8 @@ class SeqTwoByteString : public SeqString {
}
// Maximal memory usage for a single sequential two-byte string.
- static const int kMaxSize = 512 * MB - 1;
+ static const int kMaxSize =
+ OBJECT_POINTER_ALIGN(kMaxLength * 2 + kHeaderSize);
STATIC_ASSERT(static_cast<int>((kMaxSize - kHeaderSize) / sizeof(uint16_t)) >=
String::kMaxLength);