Commit 9be74766 authored by jkummerow's avatar jkummerow Committed by Commit bot

Reland^2 of [stubs] KeyedStoreGeneric: inline dictionary property stores

For dictionary-mode receivers, the KeyedStoreGeneric stub can store
properties directly in most cases. Doing so avoids the need to have
an entry in the stub cache for every map/property combination.

Original review: https://codereview.chromium.org/2504403005/

Review-Url: https://codereview.chromium.org/2528883003
Cr-Commit-Position: refs/heads/master@{#41272}
parent c4ccbaa3
......@@ -2566,10 +2566,9 @@ void Builtins::Generate_ArrayIteratorPrototypeNext(
Node* elements =
assembler.AllocateFixedArray(FAST_ELEMENTS, assembler.Int32Constant(2));
assembler.StoreFixedArrayElement(elements, assembler.Int32Constant(0),
index, SKIP_WRITE_BARRIER);
assembler.StoreFixedArrayElement(elements, assembler.Int32Constant(1),
var_value.value(), SKIP_WRITE_BARRIER);
assembler.StoreFixedArrayElement(elements, 0, index, SKIP_WRITE_BARRIER);
assembler.StoreFixedArrayElement(elements, 1, var_value.value(),
SKIP_WRITE_BARRIER);
Node* entry = assembler.Allocate(JSArray::kSize);
Node* map =
......
......@@ -293,8 +293,7 @@ compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate,
a->AllocateRegExpResult(context, num_results, start, string);
Node* const result_elements = a->LoadElements(result);
a->StoreFixedArrayElement(result_elements, a->IntPtrConstant(0), first,
SKIP_WRITE_BARRIER);
a->StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER);
a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out);
......@@ -1846,7 +1845,7 @@ compiler::Node* ReplaceGlobalCallableFastPath(
Node* const replacement_str = a->ToString(context, replacement_obj);
a->StoreFixedArrayElement(res_elems, index, replacement_str,
UPDATE_WRITE_BARRIER, mode);
UPDATE_WRITE_BARRIER, 0, mode);
a->Goto(&do_continue);
a->Bind(&do_continue);
......
This diff is collapsed.
......@@ -20,21 +20,24 @@ class StubCache;
enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
#define HEAP_CONSTANT_LIST(V) \
V(BooleanMap, BooleanMap) \
V(CodeMap, CodeMap) \
V(empty_string, EmptyString) \
V(EmptyFixedArray, EmptyFixedArray) \
V(FalseValue, False) \
V(FixedArrayMap, FixedArrayMap) \
V(FixedCOWArrayMap, FixedCOWArrayMap) \
V(FixedDoubleArrayMap, FixedDoubleArrayMap) \
V(HeapNumberMap, HeapNumberMap) \
V(MinusZeroValue, MinusZero) \
V(NanValue, Nan) \
V(NullValue, Null) \
V(TheHoleValue, TheHole) \
V(TrueValue, True) \
#define HEAP_CONSTANT_LIST(V) \
V(AccessorInfoMap, AccessorInfoMap) \
V(BooleanMap, BooleanMap) \
V(CodeMap, CodeMap) \
V(empty_string, EmptyString) \
V(EmptyFixedArray, EmptyFixedArray) \
V(FalseValue, False) \
V(FixedArrayMap, FixedArrayMap) \
V(FixedCOWArrayMap, FixedCOWArrayMap) \
V(FixedDoubleArrayMap, FixedDoubleArrayMap) \
V(FunctionTemplateInfoMap, FunctionTemplateInfoMap) \
V(HeapNumberMap, HeapNumberMap) \
V(MinusZeroValue, MinusZero) \
V(NanValue, Nan) \
V(NullValue, Null) \
V(SymbolMap, SymbolMap) \
V(TheHoleValue, TheHole) \
V(TrueValue, True) \
V(UndefinedValue, Undefined)
// Provides JavaScript-specific "macro-assembler" functionality on top of the
......@@ -357,15 +360,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Store an array element to a FixedArray.
compiler::Node* StoreFixedArrayElement(
compiler::Node* object, int index, compiler::Node* value,
WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
ParameterMode parameter_mode = INTEGER_PARAMETERS) {
return StoreFixedArrayElement(object, Int32Constant(index), value,
barrier_mode, parameter_mode);
WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
return StoreFixedArrayElement(object, IntPtrConstant(index), value,
barrier_mode, 0, INTPTR_PARAMETERS);
}
compiler::Node* StoreFixedArrayElement(
compiler::Node* object, compiler::Node* index, compiler::Node* value,
WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
int additional_offset = 0,
ParameterMode parameter_mode = INTEGER_PARAMETERS);
compiler::Node* StoreFixedDoubleArrayElement(
......@@ -762,16 +765,38 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Calculate a valid size for the a hash table.
compiler::Node* HashTableComputeCapacity(compiler::Node* at_least_space_for);
template <class Dictionary>
compiler::Node* GetNumberOfElements(compiler::Node* dictionary);
template <class Dictionary>
void SetNumberOfElements(compiler::Node* dictionary,
compiler::Node* num_elements_smi);
template <class Dictionary>
compiler::Node* GetNumberOfDeletedElements(compiler::Node* dictionary);
template <class Dictionary>
compiler::Node* GetCapacity(compiler::Node* dictionary);
template <class Dictionary>
compiler::Node* GetNextEnumerationIndex(compiler::Node* dictionary);
template <class Dictionary>
void SetNextEnumerationIndex(compiler::Node* dictionary,
compiler::Node* next_enum_index_smi);
// Looks up an entry in a NameDictionaryBase successor. If the entry is found
// control goes to {if_found} and {var_name_index} contains an index of the
// key field of the entry found. If the key is not found control goes to
// {if_not_found}.
static const int kInlinedDictionaryProbes = 4;
enum LookupMode { kFindExisting, kFindInsertionIndex };
template <typename Dictionary>
void NameDictionaryLookup(compiler::Node* dictionary,
compiler::Node* unique_name, Label* if_found,
Variable* var_name_index, Label* if_not_found,
int inlined_probes = kInlinedDictionaryProbes);
int inlined_probes = kInlinedDictionaryProbes,
LookupMode mode = kFindExisting);
compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed);
......@@ -780,6 +805,19 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* intptr_index, Label* if_found,
Variable* var_entry, Label* if_not_found);
template <class Dictionary>
void FindInsertionEntry(compiler::Node* dictionary, compiler::Node* key,
Variable* var_key_index);
template <class Dictionary>
void InsertEntry(compiler::Node* dictionary, compiler::Node* key,
compiler::Node* value, compiler::Node* index,
compiler::Node* enum_index);
template <class Dictionary>
void Add(compiler::Node* dictionary, compiler::Node* key,
compiler::Node* value, Label* bailout);
// Tries to check if {object} has own {unique_name} property.
void TryHasOwnProperty(compiler::Node* object, compiler::Node* map,
compiler::Node* instance_type,
......
......@@ -2117,7 +2117,7 @@ void StoreScriptContextFieldStub::GenerateAssembly(
Node* script_context = assembler.LoadScriptContext(context, context_index());
assembler.StoreFixedArrayElement(
script_context, assembler.IntPtrConstant(slot_index()), value,
UPDATE_WRITE_BARRIER, CodeStubAssembler::INTPTR_PARAMETERS);
UPDATE_WRITE_BARRIER, 0, CodeStubAssembler::INTPTR_PARAMETERS);
assembler.Return(value);
}
......@@ -2621,21 +2621,19 @@ compiler::Node* FastNewFunctionContextStub::Generate(
assembler->SmiFromWord32(length));
// Set up the fixed slots.
assembler->StoreFixedArrayElement(
function_context, assembler->Int32Constant(Context::CLOSURE_INDEX),
function, SKIP_WRITE_BARRIER);
assembler->StoreFixedArrayElement(
function_context, assembler->Int32Constant(Context::PREVIOUS_INDEX),
context, SKIP_WRITE_BARRIER);
assembler->StoreFixedArrayElement(
function_context, assembler->Int32Constant(Context::EXTENSION_INDEX),
assembler->TheHoleConstant(), SKIP_WRITE_BARRIER);
assembler->StoreFixedArrayElement(function_context, Context::CLOSURE_INDEX,
function, SKIP_WRITE_BARRIER);
assembler->StoreFixedArrayElement(function_context, Context::PREVIOUS_INDEX,
context, SKIP_WRITE_BARRIER);
assembler->StoreFixedArrayElement(function_context, Context::EXTENSION_INDEX,
assembler->TheHoleConstant(),
SKIP_WRITE_BARRIER);
// Copy the native context from the previous context.
Node* native_context = assembler->LoadNativeContext(context);
assembler->StoreFixedArrayElement(
function_context, assembler->Int32Constant(Context::NATIVE_CONTEXT_INDEX),
native_context, SKIP_WRITE_BARRIER);
assembler->StoreFixedArrayElement(function_context,
Context::NATIVE_CONTEXT_INDEX,
native_context, SKIP_WRITE_BARRIER);
// Initialize the rest of the slots to undefined.
Node* undefined = assembler->UndefinedConstant();
......
......@@ -1367,9 +1367,8 @@ void AccessorAssemblerImpl::KeyedLoadICGeneric(const LoadICParameters* p) {
const int32_t kMaxLinear = 210;
Label stub_cache(this);
Node* bitfield3 = LoadMapBitField3(receiver_map);
Node* nof =
DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), &stub_cache);
Node* nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
GotoIf(Uint32LessThan(Int32Constant(kMaxLinear), nof), &stub_cache);
Node* descriptors = LoadMapDescriptors(receiver_map);
Variable var_name_index(this, MachineType::PointerRepresentation());
Label if_descriptor_found(this);
......
This diff is collapsed.
......@@ -3851,6 +3851,8 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
static const bool kIsEnumerable = Shape::kIsEnumerable;
protected:
// Generic at put operation.
MUST_USE_RESULT static Handle<Derived> AtPut(
......@@ -9595,14 +9597,15 @@ class Symbol: public Name {
static const int kFlagsOffset = kNameOffset + kPointerSize;
static const int kSize = kFlagsOffset + kPointerSize;
// Flags layout.
static const int kPrivateBit = 0;
static const int kWellKnownSymbolBit = 1;
typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor;
void SymbolShortPrint(std::ostream& os);
private:
static const int kPrivateBit = 0;
static const int kWellKnownSymbolBit = 1;
const char* PrivateSymbolToName() const;
#if TRACE_MAPS
......
// Copyright 2016 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.
// Flags: --allow-natives-syntax
function f(a, i, v) {
a[i] = v;
}
f("make it generic", 0, 0);
var a = new Array(3);
// Fast properties.
f(a, "length", 2);
assertEquals(2, a.length);
// Dictionary properties.
%OptimizeObjectForAddingMultipleProperties(a, 1);
f(a, "length", 1);
assertEquals(1, a.length);
......@@ -2,7 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
class A {}
class B {}
Object.assign(B, A);
assertEquals("class B {}", B.toString());
(function() {
function f(a, i, v) {
a[i] = v;
}
f("make it generic", 0, 0);
var o = {foo: "foo"};
%OptimizeObjectForAddingMultipleProperties(o, 10);
var s = %CreatePrivateSymbol("priv");
f(o, s, "private");
%ToFastProperties(o);
var desc = Object.getOwnPropertyDescriptor(o, s);
assertEquals("private", desc.value);
assertTrue(desc.writable);
assertFalse(desc.enumerable);
assertTrue(desc.configurable);
})();
......@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Test dictionary store ICs.
// Function that stores property 'x' on an object.
......@@ -62,3 +64,27 @@ assertEquals(42, o.x);
delete o.x;
store(o);
assertEquals(42, o.x);
(function() {
var o = {};
for (var i = 0; i < 100; i++) {
var k = "key" + i;
o[k] = "foo";
delete o[k];
}
})();
(function() {
function f(a, i, v) {
a[i] = v;
}
f("make it generic", 0, 0);
var o = {};
for (var i = 0; i < 100; i++) {
var k = %InternalizeString("key" + i);
f(o, k, "foo");
delete o[k];
}
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment