Distinguish slow from fast sloppy arguments
BUG=v8:4137 LOG=n Review URL: https://codereview.chromium.org/1221713003 Cr-Commit-Position: refs/heads/master@{#29447}
This commit is contained in:
parent
3f5d39a1d6
commit
c8211b64cd
@ -6947,7 +6947,7 @@ class Internals {
|
||||
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
|
||||
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
|
||||
static const int kContextHeaderSize = 2 * kApiPointerSize;
|
||||
static const int kContextEmbedderDataIndex = 80;
|
||||
static const int kContextEmbedderDataIndex = 81;
|
||||
static const int kFullStringRepresentationMask = 0x07;
|
||||
static const int kStringEncodingMask = 0x4;
|
||||
static const int kExternalTwoByteRepresentationTag = 0x02;
|
||||
|
@ -1676,7 +1676,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
const int kNormalOffset =
|
||||
Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX);
|
||||
const int kAliasedOffset =
|
||||
Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
|
||||
__ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||
__ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
|
||||
|
@ -3225,7 +3225,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
|
||||
case FAST_ELEMENTS:
|
||||
case FAST_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -4322,7 +4323,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -1880,8 +1880,9 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
|
||||
__ Ldr(sloppy_args_map,
|
||||
ContextMemOperand(global_ctx, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
|
||||
__ Ldr(aliased_args_map,
|
||||
ContextMemOperand(global_ctx, Context::ALIASED_ARGUMENTS_MAP_INDEX));
|
||||
__ Ldr(
|
||||
aliased_args_map,
|
||||
ContextMemOperand(global_ctx, Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX));
|
||||
__ Cmp(mapped_params, 0);
|
||||
__ CmovX(sloppy_args_map, aliased_args_map, ne);
|
||||
|
||||
|
@ -3481,7 +3481,8 @@ void LCodeGen::DoLoadKeyedExternal(LLoadKeyedExternal* instr) {
|
||||
case FAST_ELEMENTS:
|
||||
case FAST_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -5192,7 +5193,8 @@ void LCodeGen::DoStoreKeyedExternal(LStoreKeyedExternal* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -1357,12 +1357,17 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
|
||||
DCHECK(IsFastObjectElementsKind(map->elements_kind()));
|
||||
}
|
||||
|
||||
{ // --- aliased arguments map
|
||||
Handle<Map> map =
|
||||
Map::Copy(isolate->sloppy_arguments_map(), "AliasedArguments");
|
||||
map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
{ // --- fast and slow aliased arguments map
|
||||
Handle<Map> map = isolate->sloppy_arguments_map();
|
||||
map = Map::Copy(map, "FastAliasedArguments");
|
||||
map->set_elements_kind(FAST_SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
DCHECK_EQ(2, map->pre_allocated_property_fields());
|
||||
native_context()->set_aliased_arguments_map(*map);
|
||||
native_context()->set_fast_aliased_arguments_map(*map);
|
||||
|
||||
map = Map::Copy(map, "SlowAliasedArguments");
|
||||
map->set_elements_kind(SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
DCHECK_EQ(2, map->pre_allocated_property_fields());
|
||||
native_context()->set_slow_aliased_arguments_map(*map);
|
||||
}
|
||||
|
||||
{ // --- strict mode arguments map
|
||||
@ -2438,7 +2443,14 @@ bool Genesis::InstallNatives() {
|
||||
{
|
||||
AccessorConstantDescriptor d(factory()->iterator_symbol(),
|
||||
arguments_iterator, attribs);
|
||||
Handle<Map> map(native_context()->aliased_arguments_map());
|
||||
Handle<Map> map(native_context()->fast_aliased_arguments_map());
|
||||
Map::EnsureDescriptorSlack(map, 1);
|
||||
map->AppendDescriptor(&d);
|
||||
}
|
||||
{
|
||||
AccessorConstantDescriptor d(factory()->iterator_symbol(),
|
||||
arguments_iterator, attribs);
|
||||
Handle<Map> map(native_context()->slow_aliased_arguments_map());
|
||||
Map::EnsureDescriptorSlack(map, 1);
|
||||
map->AppendDescriptor(&d);
|
||||
}
|
||||
|
@ -2096,9 +2096,11 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
|
||||
}
|
||||
kind_if.Else();
|
||||
|
||||
// The SLOPPY_ARGUMENTS_ELEMENTS check generates a "kind_if.Then"
|
||||
// The SLOW_SLOPPY_ARGUMENTS_ELEMENTS check generates a "kind_if.Then"
|
||||
STATIC_ASSERT(FAST_SLOPPY_ARGUMENTS_ELEMENTS <
|
||||
SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
BuildElementsKindLimitCheck(&kind_if, bit_field2,
|
||||
SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
// Non-strict elements are not handled.
|
||||
Add<HDeoptimize>(Deoptimizer::kNonStrictElementsInKeyedLoadGenericStub,
|
||||
Deoptimizer::EAGER);
|
||||
|
@ -810,7 +810,8 @@ void StoreElementStub::Generate(MacroAssembler* masm) {
|
||||
case DICTIONARY_ELEMENTS:
|
||||
ElementHandlerCompiler::GenerateStoreSlow(masm);
|
||||
break;
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -138,7 +138,8 @@ enum BindingFlags {
|
||||
V(BOUND_FUNCTION_MAP_INDEX, Map, bound_function_map) \
|
||||
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map) \
|
||||
V(SLOPPY_ARGUMENTS_MAP_INDEX, Map, sloppy_arguments_map) \
|
||||
V(ALIASED_ARGUMENTS_MAP_INDEX, Map, aliased_arguments_map) \
|
||||
V(FAST_ALIASED_ARGUMENTS_MAP_INDEX, Map, fast_aliased_arguments_map) \
|
||||
V(SLOW_ALIASED_ARGUMENTS_MAP_INDEX, Map, slow_aliased_arguments_map) \
|
||||
V(STRICT_ARGUMENTS_MAP_INDEX, Map, strict_arguments_map) \
|
||||
V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \
|
||||
V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \
|
||||
@ -337,7 +338,8 @@ class Context: public FixedArray {
|
||||
GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS,
|
||||
SECURITY_TOKEN_INDEX,
|
||||
SLOPPY_ARGUMENTS_MAP_INDEX,
|
||||
ALIASED_ARGUMENTS_MAP_INDEX,
|
||||
FAST_ALIASED_ARGUMENTS_MAP_INDEX,
|
||||
SLOW_ALIASED_ARGUMENTS_MAP_INDEX,
|
||||
STRICT_ARGUMENTS_MAP_INDEX,
|
||||
REGEXP_RESULT_MAP_INDEX,
|
||||
SLOPPY_FUNCTION_MAP_INDEX,
|
||||
|
@ -44,7 +44,8 @@ int ElementsKindToShiftSize(ElementsKind elements_kind) {
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
return kPointerSizeLog2;
|
||||
}
|
||||
UNREACHABLE();
|
||||
@ -134,21 +135,6 @@ ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
|
||||
}
|
||||
|
||||
|
||||
ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind,
|
||||
bool allow_only_packed) {
|
||||
DCHECK(IsFastElementsKind(elements_kind));
|
||||
DCHECK(elements_kind != TERMINAL_FAST_ELEMENTS_KIND);
|
||||
while (true) {
|
||||
elements_kind = GetNextTransitionElementsKind(elements_kind);
|
||||
if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) {
|
||||
return elements_kind;
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
return TERMINAL_FAST_ELEMENTS_KIND;
|
||||
}
|
||||
|
||||
|
||||
static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
|
||||
return IsFixedTypedArrayElementsKind(elements_kind) ||
|
||||
IsExternalArrayElementsKind(elements_kind);
|
||||
|
@ -28,7 +28,10 @@ enum ElementsKind {
|
||||
|
||||
// The "slow" kind.
|
||||
DICTIONARY_ELEMENTS,
|
||||
SLOPPY_ARGUMENTS_ELEMENTS,
|
||||
|
||||
FAST_SLOPPY_ARGUMENTS_ELEMENTS,
|
||||
SLOW_SLOPPY_ARGUMENTS_ELEMENTS,
|
||||
|
||||
// The "fast" kind for external arrays
|
||||
EXTERNAL_INT8_ELEMENTS,
|
||||
EXTERNAL_UINT8_ELEMENTS,
|
||||
@ -88,7 +91,8 @@ inline bool IsDictionaryElementsKind(ElementsKind kind) {
|
||||
|
||||
|
||||
inline bool IsSloppyArgumentsElements(ElementsKind kind) {
|
||||
return kind == SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
return kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
|
||||
kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
|
||||
|
||||
@ -117,7 +121,8 @@ inline bool IsFastElementsKind(ElementsKind kind) {
|
||||
|
||||
|
||||
inline bool IsTransitionElementsKind(ElementsKind kind) {
|
||||
return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind);
|
||||
return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind) ||
|
||||
kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
|
||||
|
||||
@ -239,19 +244,6 @@ inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) {
|
||||
}
|
||||
|
||||
|
||||
ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind,
|
||||
bool allow_only_packed);
|
||||
|
||||
|
||||
inline bool CanTransitionToMoreGeneralFastElementsKind(
|
||||
ElementsKind elements_kind,
|
||||
bool allow_only_packed) {
|
||||
return IsFastElementsKind(elements_kind) &&
|
||||
(elements_kind != TERMINAL_FAST_ELEMENTS_KIND &&
|
||||
(!allow_only_packed || elements_kind != FAST_ELEMENTS));
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_ELEMENTS_KIND_H_
|
||||
|
579
src/elements.cc
579
src/elements.cc
@ -47,6 +47,8 @@
|
||||
// - FixedUint8ClampedElementsAccessor
|
||||
// - DictionaryElementsAccessor
|
||||
// - SloppyArgumentsElementsAccessor
|
||||
// - FastSloppyArgumentsElementsAccessor
|
||||
// - SlowSloppyArgumentsElementsAccessor
|
||||
|
||||
|
||||
namespace v8 {
|
||||
@ -61,48 +63,45 @@ static const int kPackedSizeNotKnown = -1;
|
||||
// fast element handler for smi-only arrays. The implementation is currently
|
||||
// identical. Note that the order must match that of the ElementsKind enum for
|
||||
// the |accessor_array[]| below to work.
|
||||
#define ELEMENTS_LIST(V) \
|
||||
V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \
|
||||
V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \
|
||||
FixedArray) \
|
||||
V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \
|
||||
V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \
|
||||
V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \
|
||||
FixedDoubleArray) \
|
||||
V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \
|
||||
FixedDoubleArray) \
|
||||
V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \
|
||||
SeededNumberDictionary) \
|
||||
V(SloppyArgumentsElementsAccessor, SLOPPY_ARGUMENTS_ELEMENTS, \
|
||||
FixedArray) \
|
||||
V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, \
|
||||
ExternalInt8Array) \
|
||||
V(ExternalUint8ElementsAccessor, \
|
||||
EXTERNAL_UINT8_ELEMENTS, ExternalUint8Array) \
|
||||
V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS, \
|
||||
ExternalInt16Array) \
|
||||
V(ExternalUint16ElementsAccessor, \
|
||||
EXTERNAL_UINT16_ELEMENTS, ExternalUint16Array) \
|
||||
V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS, \
|
||||
ExternalInt32Array) \
|
||||
V(ExternalUint32ElementsAccessor, \
|
||||
EXTERNAL_UINT32_ELEMENTS, ExternalUint32Array) \
|
||||
V(ExternalFloat32ElementsAccessor, \
|
||||
EXTERNAL_FLOAT32_ELEMENTS, ExternalFloat32Array) \
|
||||
V(ExternalFloat64ElementsAccessor, \
|
||||
EXTERNAL_FLOAT64_ELEMENTS, ExternalFloat64Array) \
|
||||
V(ExternalUint8ClampedElementsAccessor, \
|
||||
EXTERNAL_UINT8_CLAMPED_ELEMENTS, \
|
||||
ExternalUint8ClampedArray) \
|
||||
V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \
|
||||
V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \
|
||||
V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \
|
||||
V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \
|
||||
V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \
|
||||
V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \
|
||||
V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
|
||||
V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
|
||||
V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \
|
||||
#define ELEMENTS_LIST(V) \
|
||||
V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \
|
||||
V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, FixedArray) \
|
||||
V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \
|
||||
V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \
|
||||
V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \
|
||||
V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \
|
||||
FixedDoubleArray) \
|
||||
V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, SeededNumberDictionary) \
|
||||
V(FastSloppyArgumentsElementsAccessor, FAST_SLOPPY_ARGUMENTS_ELEMENTS, \
|
||||
FixedArray) \
|
||||
V(SlowSloppyArgumentsElementsAccessor, SLOW_SLOPPY_ARGUMENTS_ELEMENTS, \
|
||||
FixedArray) \
|
||||
V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, ExternalInt8Array) \
|
||||
V(ExternalUint8ElementsAccessor, EXTERNAL_UINT8_ELEMENTS, \
|
||||
ExternalUint8Array) \
|
||||
V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS, \
|
||||
ExternalInt16Array) \
|
||||
V(ExternalUint16ElementsAccessor, EXTERNAL_UINT16_ELEMENTS, \
|
||||
ExternalUint16Array) \
|
||||
V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS, \
|
||||
ExternalInt32Array) \
|
||||
V(ExternalUint32ElementsAccessor, EXTERNAL_UINT32_ELEMENTS, \
|
||||
ExternalUint32Array) \
|
||||
V(ExternalFloat32ElementsAccessor, EXTERNAL_FLOAT32_ELEMENTS, \
|
||||
ExternalFloat32Array) \
|
||||
V(ExternalFloat64ElementsAccessor, EXTERNAL_FLOAT64_ELEMENTS, \
|
||||
ExternalFloat64Array) \
|
||||
V(ExternalUint8ClampedElementsAccessor, EXTERNAL_UINT8_CLAMPED_ELEMENTS, \
|
||||
ExternalUint8ClampedArray) \
|
||||
V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \
|
||||
V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \
|
||||
V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \
|
||||
V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \
|
||||
V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \
|
||||
V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \
|
||||
V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
|
||||
V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
|
||||
V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \
|
||||
FixedUint8ClampedArray)
|
||||
|
||||
|
||||
@ -550,6 +549,9 @@ template <typename ElementsAccessorSubclass,
|
||||
typename ElementsTraitsParam>
|
||||
class ElementsAccessorBase : public ElementsAccessor {
|
||||
protected:
|
||||
template <typename SloppyArgumentsElementsAccessorSubclass,
|
||||
typename ArgumentsAccessor, typename KindTraits>
|
||||
friend class SloppyArgumentsElementsAccessor;
|
||||
explicit ElementsAccessorBase(const char* name)
|
||||
: ElementsAccessor(name) { }
|
||||
|
||||
@ -922,6 +924,12 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
};
|
||||
|
||||
|
||||
class FastSloppyArgumentsElementsAccessor;
|
||||
class FastHoleyObjectElementsAccessor;
|
||||
template <typename SloppyArgumentsElementsAccessorSubclass,
|
||||
typename ArgumentsAccessor, typename KindTraits>
|
||||
class SloppyArgumentsElementsAccessor;
|
||||
|
||||
// Super class for all fast element arrays.
|
||||
template<typename FastElementsAccessorSubclass,
|
||||
typename KindTraits>
|
||||
@ -934,7 +942,9 @@ class FastElementsAccessor
|
||||
|
||||
protected:
|
||||
friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
|
||||
friend class SloppyArgumentsElementsAccessor;
|
||||
friend class SloppyArgumentsElementsAccessor<
|
||||
FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
||||
ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
||||
|
||||
typedef typename KindTraits::BackingStore BackingStore;
|
||||
|
||||
@ -1066,33 +1076,6 @@ class FastElementsAccessor
|
||||
};
|
||||
|
||||
|
||||
static inline ElementsKind ElementsKindForArray(FixedArrayBase* array) {
|
||||
switch (array->map()->instance_type()) {
|
||||
case FIXED_ARRAY_TYPE:
|
||||
if (array->IsDictionary()) {
|
||||
return DICTIONARY_ELEMENTS;
|
||||
} else {
|
||||
return FAST_HOLEY_ELEMENTS;
|
||||
}
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
return FAST_HOLEY_DOUBLE_ELEMENTS;
|
||||
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case EXTERNAL_##TYPE##_ARRAY_TYPE: \
|
||||
return EXTERNAL_##TYPE##_ELEMENTS; \
|
||||
case FIXED_##TYPE##_ARRAY_TYPE: \
|
||||
return TYPE##_ELEMENTS;
|
||||
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return FAST_HOLEY_ELEMENTS;
|
||||
}
|
||||
|
||||
|
||||
template<typename FastElementsAccessorSubclass,
|
||||
typename KindTraits>
|
||||
class FastSmiOrObjectElementsAccessor
|
||||
@ -1132,17 +1115,9 @@ class FastSmiOrObjectElementsAccessor
|
||||
CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start,
|
||||
copy_size);
|
||||
break;
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
// TODO(verwaest): This is a temporary hack to support extending
|
||||
// SLOPPY_ARGUMENTS_ELEMENTS in GrowCapacityAndConvert.
|
||||
// This case should be UNREACHABLE().
|
||||
FixedArray* parameter_map = FixedArray::cast(from);
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
ElementsKind from_kind = ElementsKindForArray(arguments);
|
||||
CopyElementsImpl(arguments, from_start, to, from_kind,
|
||||
to_start, packed_size, copy_size);
|
||||
break;
|
||||
}
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case EXTERNAL_##TYPE##_ELEMENTS: \
|
||||
case TYPE##_ELEMENTS: \
|
||||
@ -1237,7 +1212,8 @@ class FastDoubleElementsAccessor
|
||||
CopyDictionaryToDoubleElements(from, from_start, to, to_start,
|
||||
copy_size);
|
||||
break;
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
@ -1355,6 +1331,8 @@ TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR)
|
||||
#undef FIXED_ELEMENTS_ACCESSOR
|
||||
|
||||
|
||||
class SlowSloppyArgumentsElementsAccessor;
|
||||
|
||||
|
||||
class DictionaryElementsAccessor
|
||||
: public ElementsAccessorBase<DictionaryElementsAccessor,
|
||||
@ -1417,13 +1395,28 @@ class DictionaryElementsAccessor
|
||||
array->set_length(*length_obj);
|
||||
}
|
||||
|
||||
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
||||
FixedArrayBase* to, ElementsKind from_kind,
|
||||
uint32_t to_start, int packed_size,
|
||||
int copy_size) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
||||
ElementsKindTraits<DICTIONARY_ELEMENTS> >;
|
||||
friend class SlowSloppyArgumentsElementsAccessor;
|
||||
friend class SloppyArgumentsElementsAccessor<
|
||||
SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
||||
ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
||||
|
||||
static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) {
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()),
|
||||
isolate);
|
||||
bool is_arguments =
|
||||
(obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
bool is_arguments = obj->HasSloppyArgumentsElements();
|
||||
if (is_arguments) {
|
||||
backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate);
|
||||
}
|
||||
@ -1446,18 +1439,6 @@ class DictionaryElementsAccessor
|
||||
}
|
||||
}
|
||||
|
||||
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
||||
FixedArrayBase* to, ElementsKind from_kind,
|
||||
uint32_t to_start, int packed_size,
|
||||
int copy_size) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
||||
ElementsKindTraits<DICTIONARY_ELEMENTS> >;
|
||||
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
DeleteCommon(obj, key, language_mode);
|
||||
@ -1556,18 +1537,19 @@ class DictionaryElementsAccessor
|
||||
};
|
||||
|
||||
|
||||
class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
SloppyArgumentsElementsAccessor,
|
||||
ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> > {
|
||||
template <typename SloppyArgumentsElementsAccessorSubclass,
|
||||
typename ArgumentsAccessor, typename KindTraits>
|
||||
class SloppyArgumentsElementsAccessor
|
||||
: public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
||||
KindTraits> {
|
||||
public:
|
||||
explicit SloppyArgumentsElementsAccessor(const char* name)
|
||||
: ElementsAccessorBase<
|
||||
SloppyArgumentsElementsAccessor,
|
||||
ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
||||
: ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
||||
KindTraits>(name) {}
|
||||
|
||||
protected:
|
||||
friend class ElementsAccessorBase<
|
||||
SloppyArgumentsElementsAccessor,
|
||||
ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >;
|
||||
friend class ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
||||
KindTraits>;
|
||||
|
||||
static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
||||
Handle<FixedArrayBase> parameters) {
|
||||
@ -1584,8 +1566,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
// Object is not mapped, defer to the arguments.
|
||||
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)),
|
||||
isolate);
|
||||
Handle<Object> result =
|
||||
ElementsAccessor::ForArray(arguments)->Get(obj, key, arguments);
|
||||
Handle<Object> result = ArgumentsAccessor::GetImpl(obj, key, arguments);
|
||||
// Elements of the arguments object in slow mode might be slow aliases.
|
||||
if (result->IsAliasedArgumentsEntry()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
@ -1600,20 +1581,22 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
||||
if (!GetParameterMapArg(parameter_map, key)->IsTheHole()) {
|
||||
// TODO(kmillikin): We could check if this was the last aliased
|
||||
// parameter, and revert to normal elements in that case. That
|
||||
// would enable GC of the context.
|
||||
parameter_map->set_the_hole(key + 2);
|
||||
} else {
|
||||
ArgumentsAccessor::DeleteCommon(obj, key, language_mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
|
||||
uint32_t capacity) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1)));
|
||||
ElementsKind from_kind = old_elements->IsDictionary() ? DICTIONARY_ELEMENTS
|
||||
: FAST_HOLEY_ELEMENTS;
|
||||
// This method should only be called if there's a reason to update the
|
||||
// elements.
|
||||
DCHECK(IsDictionaryElementsKind(from_kind) ||
|
||||
static_cast<uint32_t>(old_elements->length()) < capacity);
|
||||
Handle<FixedArrayBase> elements =
|
||||
ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
|
||||
parameter_map->set(1, *elements);
|
||||
JSObject::ValidateElements(object);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) {
|
||||
@ -1626,7 +1609,208 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
context->set(context_index, value);
|
||||
} else {
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
ElementsAccessor::ForArray(arguments)->Set(arguments, key, value);
|
||||
ArgumentsAccessor::SetImpl(arguments, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
static MaybeHandle<AccessorPair> GetAccessorPairImpl(
|
||||
Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) {
|
||||
Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
|
||||
Handle<Object> probe(GetParameterMapArg(*parameter_map, key),
|
||||
obj->GetIsolate());
|
||||
if (!probe->IsTheHole()) {
|
||||
return MaybeHandle<AccessorPair>();
|
||||
} else {
|
||||
// If not aliased, check the arguments.
|
||||
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
||||
return ArgumentsAccessor::GetAccessorPairImpl(obj, key, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
|
||||
Handle<FixedArrayBase> parameter_map) {
|
||||
// Sloppy arguments objects are not arrays.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static uint32_t GetCapacityImpl(JSObject* holder,
|
||||
FixedArrayBase* backing_store) {
|
||||
FixedArray* parameter_map = FixedArray::cast(backing_store);
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
return parameter_map->length() - 2 +
|
||||
ArgumentsAccessor::GetCapacityImpl(holder, arguments);
|
||||
}
|
||||
|
||||
static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
if (index < length) {
|
||||
return !GetParameterMapArg(parameter_map, index)->IsTheHole();
|
||||
}
|
||||
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
return ArgumentsAccessor::HasIndexImpl(arguments, index - length);
|
||||
}
|
||||
|
||||
static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters,
|
||||
uint32_t index) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
if (index < length) return index;
|
||||
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
return ArgumentsAccessor::GetKeyForIndexImpl(arguments, index - length);
|
||||
}
|
||||
|
||||
static uint32_t GetIndexForKeyImpl(JSObject* holder,
|
||||
FixedArrayBase* parameters, uint32_t key) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
Object* probe = GetParameterMapArg(parameter_map, key);
|
||||
if (!probe->IsTheHole()) return key;
|
||||
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
uint32_t index =
|
||||
ArgumentsAccessor::GetIndexForKeyImpl(holder, arguments, key);
|
||||
if (index == kMaxUInt32) return index;
|
||||
return (parameter_map->length() - 2) + index;
|
||||
}
|
||||
|
||||
static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters,
|
||||
uint32_t index) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
if (index < length) {
|
||||
return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
|
||||
}
|
||||
index -= length;
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
return ArgumentsAccessor::GetDetailsImpl(arguments, index);
|
||||
}
|
||||
|
||||
static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) {
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
return key < length
|
||||
? parameter_map->get(key + 2)
|
||||
: Object::cast(parameter_map->GetHeap()->the_hole_value());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FastSloppyArgumentsElementsAccessor
|
||||
: public SloppyArgumentsElementsAccessor<
|
||||
FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
||||
ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > {
|
||||
public:
|
||||
friend class SloppyArgumentsElementsAccessor<
|
||||
FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
||||
ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
||||
friend class ElementsAccessorBase<
|
||||
FastSloppyArgumentsElementsAccessor,
|
||||
ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
||||
explicit FastSloppyArgumentsElementsAccessor(const char* name)
|
||||
: SloppyArgumentsElementsAccessor<
|
||||
FastSloppyArgumentsElementsAccessor,
|
||||
FastHoleyObjectElementsAccessor,
|
||||
ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
||||
|
||||
protected:
|
||||
static void AddImpl(Handle<JSObject> object, uint32_t key,
|
||||
Handle<Object> value, PropertyAttributes attributes,
|
||||
uint32_t new_capacity) {
|
||||
DCHECK_EQ(NONE, attributes);
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArrayBase> old_elements(
|
||||
FixedArrayBase::cast(parameter_map->get(1)));
|
||||
if (old_elements->IsSeededNumberDictionary() ||
|
||||
static_cast<uint32_t>(old_elements->length()) < new_capacity) {
|
||||
GrowCapacityAndConvertImpl(object, new_capacity);
|
||||
}
|
||||
SetImpl(object->elements(), key, *value);
|
||||
}
|
||||
|
||||
static void ReconfigureImpl(Handle<JSObject> object,
|
||||
Handle<FixedArrayBase> store, uint32_t index,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) {
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
JSObject::NormalizeElements(object);
|
||||
FixedArray::cast(*store)->set(1, *dictionary);
|
||||
uint32_t length = static_cast<uint32_t>(store->length()) - 2;
|
||||
if (index >= length) {
|
||||
index = dictionary->FindEntry(index - length) + length;
|
||||
}
|
||||
object->GetElementsAccessor()->Reconfigure(object, store, index, value,
|
||||
attributes);
|
||||
}
|
||||
|
||||
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
||||
FixedArrayBase* to, ElementsKind from_kind,
|
||||
uint32_t to_start, int packed_size,
|
||||
int copy_size) {
|
||||
DCHECK(!to->IsDictionary());
|
||||
if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
|
||||
CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS,
|
||||
to_start, copy_size);
|
||||
} else {
|
||||
DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, from_kind);
|
||||
CopyObjectToObjectElements(from, FAST_HOLEY_ELEMENTS, from_start, to,
|
||||
FAST_HOLEY_ELEMENTS, to_start, copy_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
|
||||
uint32_t capacity) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1)));
|
||||
ElementsKind from_kind = object->GetElementsKind();
|
||||
// This method should only be called if there's a reason to update the
|
||||
// elements.
|
||||
DCHECK(from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS ||
|
||||
static_cast<uint32_t>(old_elements->length()) < capacity);
|
||||
Handle<FixedArrayBase> elements =
|
||||
ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
|
||||
Handle<Map> new_map = JSObject::GetElementsTransitionMap(
|
||||
object, FAST_SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
JSObject::MigrateToMap(object, new_map);
|
||||
parameter_map->set(1, *elements);
|
||||
JSObject::ValidateElements(object);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SlowSloppyArgumentsElementsAccessor
|
||||
: public SloppyArgumentsElementsAccessor<
|
||||
SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
||||
ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > {
|
||||
public:
|
||||
friend class ElementsAccessorBase<
|
||||
SlowSloppyArgumentsElementsAccessor,
|
||||
ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
||||
friend class SloppyArgumentsElementsAccessor<
|
||||
SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
||||
ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
||||
explicit SlowSloppyArgumentsElementsAccessor(const char* name)
|
||||
: SloppyArgumentsElementsAccessor<
|
||||
SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
||||
ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
||||
|
||||
protected:
|
||||
static void AddImpl(Handle<JSObject> object, uint32_t key,
|
||||
Handle<Object> value, PropertyAttributes attributes,
|
||||
uint32_t new_capacity) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArrayBase> old_elements(
|
||||
FixedArrayBase::cast(parameter_map->get(1)));
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
old_elements->IsSeededNumberDictionary()
|
||||
? Handle<SeededNumberDictionary>::cast(old_elements)
|
||||
: JSObject::NormalizeElements(object);
|
||||
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
||||
Handle<SeededNumberDictionary> new_dictionary =
|
||||
SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details);
|
||||
if (attributes != NONE) new_dictionary->set_requires_slow_elements();
|
||||
if (*dictionary != *new_dictionary) {
|
||||
FixedArray::cast(object->elements())->set(1, *new_dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1653,168 +1837,21 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
}
|
||||
|
||||
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
||||
Handle<SeededNumberDictionary> arguments =
|
||||
parameter_map->get(1)->IsSeededNumberDictionary()
|
||||
? handle(SeededNumberDictionary::cast(parameter_map->get(1)))
|
||||
: JSObject::NormalizeElements(object);
|
||||
Handle<SeededNumberDictionary> arguments(
|
||||
SeededNumberDictionary::cast(parameter_map->get(1)));
|
||||
arguments = SeededNumberDictionary::AddNumberEntry(arguments, index,
|
||||
value, details);
|
||||
parameter_map->set(1, *arguments);
|
||||
} else {
|
||||
Handle<FixedArrayBase> arguments(
|
||||
FixedArrayBase::cast(parameter_map->get(1)));
|
||||
ElementsAccessor::ForArray(arguments)
|
||||
->Reconfigure(object, arguments, index - length, value, attributes);
|
||||
DictionaryElementsAccessor::ReconfigureImpl(
|
||||
object, arguments, index - length, value, attributes);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddImpl(Handle<JSObject> object, uint32_t key,
|
||||
Handle<Object> value, PropertyAttributes attributes,
|
||||
uint32_t new_capacity) {
|
||||
DCHECK_EQ(NONE, attributes);
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArrayBase> old_elements(
|
||||
FixedArrayBase::cast(parameter_map->get(1)));
|
||||
if (old_elements->IsSeededNumberDictionary() ||
|
||||
static_cast<uint32_t>(old_elements->length()) < new_capacity) {
|
||||
GrowCapacityAndConvertImpl(object, new_capacity);
|
||||
}
|
||||
SetImpl(object->elements(), key, *value);
|
||||
}
|
||||
|
||||
static MaybeHandle<AccessorPair> GetAccessorPairImpl(
|
||||
Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) {
|
||||
Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
|
||||
Handle<Object> probe(GetParameterMapArg(*parameter_map, key),
|
||||
obj->GetIsolate());
|
||||
if (!probe->IsTheHole()) {
|
||||
return MaybeHandle<AccessorPair>();
|
||||
} else {
|
||||
// If not aliased, check the arguments.
|
||||
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
||||
return ElementsAccessor::ForArray(arguments)
|
||||
->GetAccessorPair(obj, key, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
|
||||
Handle<FixedArrayBase> parameter_map) {
|
||||
// Sloppy arguments objects are not arrays.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
|
||||
Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate);
|
||||
if (!probe->IsTheHole()) {
|
||||
// TODO(kmillikin): We could check if this was the last aliased
|
||||
// parameter, and revert to normal elements in that case. That
|
||||
// would enable GC of the context.
|
||||
parameter_map->set_the_hole(key + 2);
|
||||
} else {
|
||||
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
||||
if (arguments->IsDictionary()) {
|
||||
DictionaryElementsAccessor::DeleteCommon(obj, key, language_mode);
|
||||
} else {
|
||||
// It's difficult to access the version of DeleteCommon that is declared
|
||||
// in the templatized super class, call the concrete implementation in
|
||||
// the class for the most generalized ElementsKind subclass.
|
||||
FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
||||
FixedArrayBase* to, ElementsKind from_kind,
|
||||
uint32_t to_start, int packed_size,
|
||||
int copy_size) {
|
||||
DCHECK(!to->IsDictionary());
|
||||
if (from_kind == DICTIONARY_ELEMENTS) {
|
||||
CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS,
|
||||
to_start, copy_size);
|
||||
} else {
|
||||
DCHECK_EQ(FAST_HOLEY_ELEMENTS, from_kind);
|
||||
CopyObjectToObjectElements(from, from_kind, from_start, to,
|
||||
FAST_HOLEY_ELEMENTS, to_start, copy_size);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t GetCapacityImpl(JSObject* holder,
|
||||
FixedArrayBase* backing_store) {
|
||||
FixedArray* parameter_map = FixedArray::cast(backing_store);
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
return parameter_map->length() - 2 +
|
||||
ForArray(arguments)->GetCapacity(holder, arguments);
|
||||
}
|
||||
|
||||
static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
if (index < length) {
|
||||
return !GetParameterMapArg(parameter_map, index)->IsTheHole();
|
||||
}
|
||||
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
return ForArray(arguments)->HasIndex(arguments, index - length);
|
||||
}
|
||||
|
||||
static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters,
|
||||
uint32_t index) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
if (index < length) return index;
|
||||
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
return ForArray(arguments)->GetKeyForIndex(arguments, index - length);
|
||||
}
|
||||
|
||||
static uint32_t GetIndexForKeyImpl(JSObject* holder,
|
||||
FixedArrayBase* parameters, uint32_t key) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
Object* probe = GetParameterMapArg(parameter_map, key);
|
||||
if (!probe->IsTheHole()) return key;
|
||||
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
uint32_t index = ElementsAccessor::ForArray(arguments)
|
||||
->GetIndexForKey(holder, arguments, key);
|
||||
if (index == kMaxUInt32) return index;
|
||||
return (parameter_map->length() - 2) + index;
|
||||
}
|
||||
|
||||
static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters,
|
||||
uint32_t index) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
if (index < length) {
|
||||
return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
|
||||
}
|
||||
index -= length;
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
return ElementsAccessor::ForArray(arguments)->GetDetails(arguments, index);
|
||||
}
|
||||
|
||||
private:
|
||||
static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) {
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
return key < length
|
||||
? parameter_map->get(key + 2)
|
||||
: Object::cast(parameter_map->GetHeap()->the_hole_value());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
|
||||
return elements_accessors_[ElementsKindForArray(array)];
|
||||
}
|
||||
|
||||
|
||||
ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) {
|
||||
return ForArray(*array);
|
||||
}
|
||||
|
||||
|
||||
void ElementsAccessor::InitializeOncePerProcess() {
|
||||
static ElementsAccessor* accessor_array[] = {
|
||||
#define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind),
|
||||
|
@ -149,7 +149,6 @@ class ElementsAccessor {
|
||||
uint32_t new_capacity) = 0;
|
||||
|
||||
protected:
|
||||
friend class SloppyArgumentsElementsAccessor;
|
||||
friend class LookupIterator;
|
||||
|
||||
static ElementsAccessor* ForArray(FixedArrayBase* array);
|
||||
|
@ -7157,7 +7157,8 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
|
||||
|
||||
|
||||
static bool CanInlineElementAccess(Handle<Map> map) {
|
||||
return map->IsJSObjectMap() && !map->has_slow_elements_kind() &&
|
||||
return map->IsJSObjectMap() && !map->has_dictionary_elements() &&
|
||||
!map->has_sloppy_arguments_elements() &&
|
||||
!map->has_indexed_interceptor() && !map->is_access_check_needed();
|
||||
}
|
||||
|
||||
@ -7263,7 +7264,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
||||
elements_kind != GetInitialFastElementsKind()) {
|
||||
possible_transitioned_maps.Add(map);
|
||||
}
|
||||
if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
|
||||
if (IsSloppyArgumentsElements(elements_kind)) {
|
||||
HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key,
|
||||
val);
|
||||
*has_side_effects = result->HasObservableSideEffects();
|
||||
@ -7274,7 +7275,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
||||
for (int i = 0; i < maps->length(); ++i) {
|
||||
Handle<Map> map = maps->at(i);
|
||||
Handle<Map> transitioned_map =
|
||||
map->FindTransitionedMap(&possible_transitioned_maps);
|
||||
Map::FindTransitionedMap(map, &possible_transitioned_maps);
|
||||
transition_target.Add(transitioned_map);
|
||||
}
|
||||
|
||||
|
@ -899,9 +899,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ jmp(&instantiate, Label::kNear);
|
||||
|
||||
__ bind(&has_mapped_parameters);
|
||||
__ mov(
|
||||
edi,
|
||||
Operand(edi, Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX)));
|
||||
__ mov(edi, Operand(edi, Context::SlotOffset(
|
||||
Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX)));
|
||||
__ bind(&instantiate);
|
||||
|
||||
// eax = address of new object (tagged)
|
||||
|
@ -3092,7 +3092,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -4192,7 +4193,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
|
||||
Handle<Map> receiver_map(receiver_maps->at(i));
|
||||
Handle<Code> cached_stub;
|
||||
Handle<Map> transitioned_map =
|
||||
receiver_map->FindTransitionedMap(receiver_maps);
|
||||
Map::FindTransitionedMap(receiver_map, receiver_maps);
|
||||
|
||||
// TODO(mvstanton): The code below is doing pessimistic elements
|
||||
// transitions. I would like to stop doing that and rely on Allocation Site
|
||||
|
@ -1779,7 +1779,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
const int kNormalOffset =
|
||||
Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX);
|
||||
const int kAliasedOffset =
|
||||
Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
|
||||
__ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||
__ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset));
|
||||
|
@ -3149,7 +3149,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -4283,7 +4284,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -1778,7 +1778,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
const int kNormalOffset =
|
||||
Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX);
|
||||
const int kAliasedOffset =
|
||||
Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
|
||||
__ ld(a4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||
__ ld(a4, FieldMemOperand(a4, GlobalObject::kNativeContextOffset));
|
||||
|
@ -3278,7 +3278,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -4485,7 +4486,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ void JSObject::JSObjectVerify() {
|
||||
VerifyHeapPointer(properties());
|
||||
VerifyHeapPointer(elements());
|
||||
|
||||
if (GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS) {
|
||||
if (HasSloppyArgumentsElements()) {
|
||||
CHECK(this->elements()->IsFixedArray());
|
||||
CHECK_GE(this->elements()->length(), 2);
|
||||
}
|
||||
@ -1104,7 +1104,8 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) {
|
||||
dict->Capacity() - dict->NumberOfElements();
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6223,7 +6223,7 @@ ElementsKind JSObject::GetElementsKind() {
|
||||
fixed_array->IsFixedArray() &&
|
||||
fixed_array->IsDictionary()) ||
|
||||
(kind > DICTIONARY_ELEMENTS));
|
||||
DCHECK((kind != SLOPPY_ARGUMENTS_ELEMENTS) ||
|
||||
DCHECK(!IsSloppyArgumentsElements(kind) ||
|
||||
(elements()->IsFixedArray() && elements()->length() >= 2));
|
||||
}
|
||||
#endif
|
||||
@ -6266,8 +6266,18 @@ bool JSObject::HasDictionaryElements() {
|
||||
}
|
||||
|
||||
|
||||
bool JSObject::HasFastArgumentsElements() {
|
||||
return GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
|
||||
|
||||
bool JSObject::HasSlowArgumentsElements() {
|
||||
return GetElementsKind() == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
|
||||
|
||||
bool JSObject::HasSloppyArgumentsElements() {
|
||||
return GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
return IsSloppyArgumentsElements(GetElementsKind());
|
||||
}
|
||||
|
||||
|
||||
|
@ -340,7 +340,8 @@ void JSObject::PrintElements(std::ostream& os) { // NOLINT
|
||||
case DICTIONARY_ELEMENTS:
|
||||
elements()->Print(os);
|
||||
break;
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
FixedArray* p = FixedArray::cast(elements());
|
||||
os << " parameter map:";
|
||||
for (int i = 2; i < p->length(); i++) {
|
||||
|
213
src/objects.cc
213
src/objects.cc
@ -2425,7 +2425,9 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
|
||||
|
||||
ElementsKind from_kind = root_map->elements_kind();
|
||||
ElementsKind to_kind = old_map->elements_kind();
|
||||
// TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
|
||||
if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
|
||||
to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
|
||||
!(IsTransitionableFastElementsKind(from_kind) &&
|
||||
IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
|
||||
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
|
||||
@ -3586,51 +3588,38 @@ int AccessorInfo::AppendUnique(Handle<Object> descriptors,
|
||||
}
|
||||
|
||||
|
||||
static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
|
||||
DCHECK(!map.is_null());
|
||||
static bool ContainsMap(MapHandleList* maps, Map* map) {
|
||||
DCHECK_NOT_NULL(map);
|
||||
for (int i = 0; i < maps->length(); ++i) {
|
||||
if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
|
||||
if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
static Handle<T> MaybeNull(T* p) {
|
||||
if (p == NULL) return Handle<T>::null();
|
||||
return Handle<T>(p);
|
||||
}
|
||||
|
||||
|
||||
Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
|
||||
ElementsKind kind = elements_kind();
|
||||
Handle<Map> transitioned_map = Handle<Map>::null();
|
||||
Handle<Map> current_map(this);
|
||||
Handle<Map> Map::FindTransitionedMap(Handle<Map> map,
|
||||
MapHandleList* candidates) {
|
||||
ElementsKind kind = map->elements_kind();
|
||||
bool packed = IsFastPackedElementsKind(kind);
|
||||
|
||||
Map* transition = nullptr;
|
||||
if (IsTransitionableFastElementsKind(kind)) {
|
||||
while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
|
||||
kind = GetNextMoreGeneralFastElementsKind(kind, false);
|
||||
Handle<Map> maybe_transitioned_map =
|
||||
MaybeNull(current_map->LookupElementsTransitionMap(kind));
|
||||
if (maybe_transitioned_map.is_null()) break;
|
||||
if (ContainsMap(candidates, maybe_transitioned_map) &&
|
||||
(packed || !IsFastPackedElementsKind(kind))) {
|
||||
transitioned_map = maybe_transitioned_map;
|
||||
if (!IsFastPackedElementsKind(kind)) packed = false;
|
||||
for (Map* current = map->ElementsTransitionMap();
|
||||
current != nullptr && current->has_fast_elements();
|
||||
current = current->ElementsTransitionMap()) {
|
||||
if (ContainsMap(candidates, current) &&
|
||||
(packed || !IsFastPackedElementsKind(current->elements_kind()))) {
|
||||
transition = current;
|
||||
packed = packed && IsFastPackedElementsKind(current->elements_kind());
|
||||
}
|
||||
current_map = maybe_transitioned_map;
|
||||
}
|
||||
}
|
||||
return transitioned_map;
|
||||
return transition == nullptr ? Handle<Map>() : handle(transition);
|
||||
}
|
||||
|
||||
|
||||
static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
|
||||
Map* current_map = map;
|
||||
int target_kind =
|
||||
IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
|
||||
? to_kind
|
||||
: TERMINAL_FAST_ELEMENTS_KIND;
|
||||
|
||||
// Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
|
||||
// allows to change elements from arbitrary kind to any ExternalArray
|
||||
@ -3646,20 +3635,14 @@ static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
|
||||
}
|
||||
|
||||
ElementsKind kind = map->elements_kind();
|
||||
while (kind != target_kind) {
|
||||
kind = GetNextTransitionElementsKind(kind);
|
||||
while (kind != to_kind) {
|
||||
Map* next_map = current_map->ElementsTransitionMap();
|
||||
if (next_map == NULL) return current_map;
|
||||
if (next_map == nullptr) return current_map;
|
||||
kind = next_map->elements_kind();
|
||||
current_map = next_map;
|
||||
}
|
||||
|
||||
Map* next_map = current_map->ElementsTransitionMap();
|
||||
if (to_kind != kind && next_map != NULL) {
|
||||
DCHECK(to_kind == DICTIONARY_ELEMENTS);
|
||||
if (next_map->elements_kind() == to_kind) return next_map;
|
||||
}
|
||||
|
||||
DCHECK(current_map->elements_kind() == target_kind);
|
||||
DCHECK_EQ(to_kind, current_map->elements_kind());
|
||||
return current_map;
|
||||
}
|
||||
|
||||
@ -3667,7 +3650,7 @@ static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
|
||||
Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
|
||||
Map* to_map = FindClosestElementsTransition(this, to_kind);
|
||||
if (to_map->elements_kind() == to_kind) return to_map;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -3708,9 +3691,11 @@ static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
|
||||
flag = OMIT_TRANSITION;
|
||||
} else {
|
||||
flag = INSERT_TRANSITION;
|
||||
while (kind != to_kind && !IsTerminalElementsKind(kind)) {
|
||||
kind = GetNextTransitionElementsKind(kind);
|
||||
current_map = Map::CopyAsElementsKind(current_map, kind, flag);
|
||||
if (IsFastElementsKind(kind)) {
|
||||
while (kind != to_kind && !IsTerminalElementsKind(kind)) {
|
||||
kind = GetNextTransitionElementsKind(kind);
|
||||
current_map = Map::CopyAsElementsKind(current_map, kind, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3732,16 +3717,28 @@ Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
|
||||
|
||||
Isolate* isolate = map->GetIsolate();
|
||||
Context* native_context = isolate->context()->native_context();
|
||||
Object* maybe_array_maps = map->is_strong()
|
||||
? native_context->js_array_strong_maps()
|
||||
: native_context->js_array_maps();
|
||||
if (maybe_array_maps->IsFixedArray()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
|
||||
if (array_maps->get(from_kind) == *map) {
|
||||
Object* maybe_transitioned_map = array_maps->get(to_kind);
|
||||
if (maybe_transitioned_map->IsMap()) {
|
||||
return handle(Map::cast(maybe_transitioned_map));
|
||||
if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
|
||||
if (*map == native_context->fast_aliased_arguments_map()) {
|
||||
DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
|
||||
return handle(native_context->slow_aliased_arguments_map());
|
||||
}
|
||||
} else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
|
||||
if (*map == native_context->slow_aliased_arguments_map()) {
|
||||
DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
|
||||
return handle(native_context->fast_aliased_arguments_map());
|
||||
}
|
||||
} else {
|
||||
Object* maybe_array_maps = map->is_strong()
|
||||
? native_context->js_array_strong_maps()
|
||||
: native_context->js_array_maps();
|
||||
if (maybe_array_maps->IsFixedArray()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
|
||||
if (array_maps->get(from_kind) == *map) {
|
||||
Object* maybe_transitioned_map = array_maps->get(to_kind);
|
||||
if (maybe_transitioned_map->IsMap()) {
|
||||
return handle(Map::cast(maybe_transitioned_map));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3750,8 +3747,8 @@ Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
|
||||
bool allow_store_transition = IsTransitionElementsKind(from_kind);
|
||||
// Only store fast element maps in ascending generality.
|
||||
if (IsFastElementsKind(to_kind)) {
|
||||
allow_store_transition &=
|
||||
IsTransitionableFastElementsKind(from_kind) &&
|
||||
allow_store_transition =
|
||||
allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
|
||||
IsMoreGeneralElementsKindTransition(from_kind, to_kind);
|
||||
}
|
||||
|
||||
@ -4844,15 +4841,15 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
||||
dictionary = CopyFastElementsToDictionary(array, length, dictionary);
|
||||
|
||||
// Switch to using the dictionary as the backing storage for elements.
|
||||
ElementsKind target_kind =
|
||||
is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS;
|
||||
Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
|
||||
// Set the new map first to satify the elements type assert in set_elements().
|
||||
JSObject::MigrateToMap(object, new_map);
|
||||
|
||||
if (is_arguments) {
|
||||
FixedArray::cast(object->elements())->set(1, *dictionary);
|
||||
} else {
|
||||
// Set the new map first to satify the elements type assert in
|
||||
// set_elements().
|
||||
Handle<Map> new_map =
|
||||
JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
|
||||
|
||||
JSObject::MigrateToMap(object, new_map);
|
||||
object->set_elements(*dictionary);
|
||||
}
|
||||
|
||||
@ -4866,8 +4863,7 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
||||
}
|
||||
#endif
|
||||
|
||||
DCHECK(object->HasDictionaryElements() ||
|
||||
object->HasDictionaryArgumentsElements());
|
||||
DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
@ -5371,7 +5367,8 @@ bool JSObject::ReferencesObject(Object* obj) {
|
||||
if (ReferencesObjectFromElements(elements, kind, obj)) return true;
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
FixedArray* parameter_map = FixedArray::cast(elements());
|
||||
// Check the mapped parameters.
|
||||
int length = parameter_map->length();
|
||||
@ -5469,8 +5466,7 @@ MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
|
||||
|
||||
// If there are fast elements we normalize.
|
||||
Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
|
||||
DCHECK(object->HasDictionaryElements() ||
|
||||
object->HasDictionaryArgumentsElements());
|
||||
DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
|
||||
|
||||
// Make sure that we never go back to fast case.
|
||||
dictionary->set_requires_slow_elements();
|
||||
@ -5898,7 +5894,8 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
|
||||
@ -6315,7 +6312,8 @@ void JSObject::DefineElementAccessor(Handle<JSObject> object,
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
// Ascertain whether we have read-only properties or an existing
|
||||
// getter/setter pair in an arguments elements dictionary backing
|
||||
// store.
|
||||
@ -6381,8 +6379,7 @@ void JSObject::SetElementCallback(Handle<JSObject> object,
|
||||
// Normalize elements to make this operation simple.
|
||||
bool had_dictionary_elements = object->HasDictionaryElements();
|
||||
Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
|
||||
DCHECK(object->HasDictionaryElements() ||
|
||||
object->HasDictionaryArgumentsElements());
|
||||
DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
|
||||
// Update the dictionary with the new ACCESSOR_CONSTANT property.
|
||||
dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
|
||||
details);
|
||||
@ -7164,7 +7161,8 @@ Handle<Map> Map::PrepareForDataElement(Handle<Map> map, Handle<Object> value) {
|
||||
case FAST_ELEMENTS:
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case EXTERNAL_##TYPE##_ELEMENTS: \
|
||||
case TYPE##_ELEMENTS:
|
||||
@ -12334,30 +12332,6 @@ void JSObject::EnsureCanContainElements(Handle<JSObject> object,
|
||||
}
|
||||
|
||||
|
||||
bool JSObject::HasFastArgumentsElements() {
|
||||
Heap* heap = GetHeap();
|
||||
if (!elements()->IsFixedArray()) return false;
|
||||
FixedArray* elements = FixedArray::cast(this->elements());
|
||||
if (elements->map() != heap->sloppy_arguments_elements_map()) {
|
||||
return false;
|
||||
}
|
||||
FixedArray* arguments = FixedArray::cast(elements->get(1));
|
||||
return !arguments->IsDictionary();
|
||||
}
|
||||
|
||||
|
||||
bool JSObject::HasDictionaryArgumentsElements() {
|
||||
Heap* heap = GetHeap();
|
||||
if (!elements()->IsFixedArray()) return false;
|
||||
FixedArray* elements = FixedArray::cast(this->elements());
|
||||
if (elements->map() != heap->sloppy_arguments_elements_map()) {
|
||||
return false;
|
||||
}
|
||||
FixedArray* arguments = FixedArray::cast(elements->get(1));
|
||||
return arguments->IsDictionary();
|
||||
}
|
||||
|
||||
|
||||
ElementsAccessor* JSObject::GetElementsAccessor() {
|
||||
return ElementsAccessor::ForKind(GetElementsKind());
|
||||
}
|
||||
@ -12424,7 +12398,9 @@ bool JSObject::WouldConvertToSlowElements(uint32_t index) {
|
||||
|
||||
|
||||
static ElementsKind BestFittingFastElementsKind(JSObject* object) {
|
||||
if (object->HasSloppyArgumentsElements()) return SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
if (object->HasSloppyArgumentsElements()) {
|
||||
return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
DCHECK(object->HasDictionaryElements());
|
||||
SeededNumberDictionary* dictionary = object->element_dictionary();
|
||||
ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
|
||||
@ -12491,49 +12467,34 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
|
||||
|
||||
ElementsKind kind = object->GetElementsKind();
|
||||
FixedArrayBase* elements = object->elements();
|
||||
ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
|
||||
if (IsSloppyArgumentsElements(kind)) {
|
||||
elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
|
||||
dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
|
||||
if (attributes != NONE) {
|
||||
kind = DICTIONARY_ELEMENTS;
|
||||
kind = dictionary_kind;
|
||||
} else if (elements->IsSeededNumberDictionary()) {
|
||||
kind = ShouldConvertToFastElements(*object,
|
||||
SeededNumberDictionary::cast(elements),
|
||||
index, &new_capacity)
|
||||
? BestFittingFastElementsKind(*object)
|
||||
: DICTIONARY_ELEMENTS; // Overwrite in case of arguments.
|
||||
: dictionary_kind; // Overwrite in case of arguments.
|
||||
} else if (ShouldConvertToSlowElements(
|
||||
*object, static_cast<uint32_t>(elements->length()), index,
|
||||
&new_capacity)) {
|
||||
kind = DICTIONARY_ELEMENTS;
|
||||
kind = dictionary_kind;
|
||||
}
|
||||
|
||||
if (kind == DICTIONARY_ELEMENTS && object->HasSloppyArgumentsElements()) {
|
||||
// TODO(verwaest): Distinguish fast/slow sloppy elements in ElementsKind.
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
elements->IsSeededNumberDictionary()
|
||||
? handle(SeededNumberDictionary::cast(elements))
|
||||
: NormalizeElements(object);
|
||||
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
||||
Handle<SeededNumberDictionary> new_dictionary =
|
||||
SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
|
||||
details);
|
||||
if (attributes != NONE) new_dictionary->set_requires_slow_elements();
|
||||
if (*dictionary != *new_dictionary) {
|
||||
FixedArray::cast(object->elements())->set(1, *new_dictionary);
|
||||
}
|
||||
} else {
|
||||
ElementsKind to = value->OptimalElementsKind();
|
||||
if (IsHoleyElementsKind(kind) || !object->IsJSArray() ||
|
||||
index > old_length) {
|
||||
to = GetHoleyElementsKind(to);
|
||||
kind = GetHoleyElementsKind(kind);
|
||||
}
|
||||
to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
|
||||
ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
|
||||
accessor->Add(object, index, value, attributes, new_capacity);
|
||||
ElementsKind to = value->OptimalElementsKind();
|
||||
if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
|
||||
to = GetHoleyElementsKind(to);
|
||||
kind = GetHoleyElementsKind(kind);
|
||||
}
|
||||
to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
|
||||
ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
|
||||
accessor->Add(object, index, value, attributes, new_capacity);
|
||||
|
||||
uint32_t new_length = old_length;
|
||||
Handle<Object> new_length_handle;
|
||||
@ -12792,7 +12753,8 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
|
||||
FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
|
||||
FixedArray* backing_store = NULL;
|
||||
switch (GetElementsKind()) {
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
backing_store_base =
|
||||
FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
|
||||
backing_store = FixedArray::cast(backing_store_base);
|
||||
@ -13289,7 +13251,8 @@ int JSObject::GetOwnElementKeys(FixedArray* storage,
|
||||
counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
FixedArray* parameter_map = FixedArray::cast(elements());
|
||||
int mapped_length = parameter_map->length() - 2;
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
|
@ -1835,8 +1835,8 @@ class JSObject: public JSReceiver {
|
||||
inline bool HasFixedFloat32Elements();
|
||||
inline bool HasFixedFloat64Elements();
|
||||
|
||||
bool HasFastArgumentsElements();
|
||||
bool HasDictionaryArgumentsElements();
|
||||
inline bool HasFastArgumentsElements();
|
||||
inline bool HasSlowArgumentsElements();
|
||||
inline SeededNumberDictionary* element_dictionary(); // Gets slow elements.
|
||||
|
||||
// Requires: HasFastElements().
|
||||
@ -5708,7 +5708,7 @@ class Map: public HeapObject {
|
||||
}
|
||||
|
||||
inline bool has_sloppy_arguments_elements() {
|
||||
return elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
return IsSloppyArgumentsElements(elements_kind());
|
||||
}
|
||||
|
||||
inline bool has_external_array_elements() {
|
||||
@ -5723,11 +5723,6 @@ class Map: public HeapObject {
|
||||
return IsDictionaryElementsKind(elements_kind());
|
||||
}
|
||||
|
||||
inline bool has_slow_elements_kind() {
|
||||
return elements_kind() == DICTIONARY_ELEMENTS
|
||||
|| elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
|
||||
static bool IsValidElementsTransition(ElementsKind from_kind,
|
||||
ElementsKind to_kind);
|
||||
|
||||
@ -6052,7 +6047,8 @@ class Map: public HeapObject {
|
||||
// Returns the transitioned map for this map with the most generic
|
||||
// elements_kind that's found in |candidates|, or null handle if no match is
|
||||
// found at all.
|
||||
Handle<Map> FindTransitionedMap(MapHandleList* candidates);
|
||||
static Handle<Map> FindTransitionedMap(Handle<Map> map,
|
||||
MapHandleList* candidates);
|
||||
|
||||
bool CanTransition() {
|
||||
// Only JSObject and subtypes have map transitions and back pointers.
|
||||
|
@ -1792,7 +1792,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
const int kNormalOffset =
|
||||
Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX);
|
||||
const int kAliasedOffset =
|
||||
Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
|
||||
__ LoadP(r7,
|
||||
MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||
|
@ -3360,7 +3360,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
|
||||
case FAST_ELEMENTS:
|
||||
case FAST_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -4589,7 +4590,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -295,7 +295,8 @@ static uint32_t EstimateElementCount(Handle<JSArray> array) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case EXTERNAL_##TYPE##_ELEMENTS: \
|
||||
case TYPE##_ELEMENTS:
|
||||
@ -436,7 +437,8 @@ static void CollectElementIndices(Handle<JSObject> object, uint32_t range,
|
||||
if (length == range) return; // All indices accounted for already.
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
MaybeHandle<Object> length_obj =
|
||||
Object::GetProperty(object, isolate->factory()->length_string());
|
||||
double length_num = length_obj.ToHandleChecked()->Number();
|
||||
@ -706,7 +708,8 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
|
||||
isolate, receiver, false, false, visitor);
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
HandleScope loop_scope(isolate);
|
||||
Handle<Object> element;
|
||||
|
@ -383,11 +383,7 @@ static Handle<JSObject> NewSloppyArguments(Isolate* isolate,
|
||||
Handle<FixedArray> parameter_map =
|
||||
isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
|
||||
parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
|
||||
|
||||
Handle<Map> map = Map::Copy(handle(result->map()), "NewSloppyArguments");
|
||||
map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
|
||||
result->set_map(*map);
|
||||
result->set_map(isolate->native_context()->fast_aliased_arguments_map());
|
||||
result->set_elements(*parameter_map);
|
||||
|
||||
// Store the context and the arguments array at the beginning of the
|
||||
|
@ -674,7 +674,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex)));
|
||||
__ jmp(&instantiate, Label::kNear);
|
||||
|
||||
const int kAliasedIndex = Context::ALIASED_ARGUMENTS_MAP_INDEX;
|
||||
const int kAliasedIndex = Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX;
|
||||
__ bind(&has_mapped_parameters);
|
||||
__ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex)));
|
||||
__ bind(&instantiate);
|
||||
|
@ -3138,7 +3138,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -4360,7 +4361,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -580,9 +580,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ jmp(&instantiate, Label::kNear);
|
||||
|
||||
__ bind(&has_mapped_parameters);
|
||||
__ mov(
|
||||
edi,
|
||||
Operand(edi, Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX)));
|
||||
__ mov(edi, Operand(edi, Context::SlotOffset(
|
||||
Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX)));
|
||||
__ bind(&instantiate);
|
||||
|
||||
// eax = address of new object (tagged)
|
||||
|
@ -3364,7 +3364,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -4618,7 +4619,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
case DICTIONARY_ELEMENTS:
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user