summaryrefslogtreecommitdiff
path: root/chromium/v8/src/code-stub-assembler.h
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-03-08 10:28:10 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-03-20 13:40:30 +0000
commite733310db58160074f574c429d48f8308c0afe17 (patch)
treef8aef4b7e62a69928dbcf880620eece20f98c6df /chromium/v8/src/code-stub-assembler.h
parent2f583e4aec1ae3a86fa047829c96b310dc12ecdf (diff)
downloadqtwebengine-chromium-e733310db58160074f574c429d48f8308c0afe17.tar.gz
BASELINE: Update Chromium to 56.0.2924.122
Change-Id: I4e04de8f47e47e501c46ed934c76a431c6337ced Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/v8/src/code-stub-assembler.h')
-rw-r--r--chromium/v8/src/code-stub-assembler.h476
1 files changed, 443 insertions, 33 deletions
diff --git a/chromium/v8/src/code-stub-assembler.h b/chromium/v8/src/code-stub-assembler.h
index 25c7d5a8c82..f8f2686f8d6 100644
--- a/chromium/v8/src/code-stub-assembler.h
+++ b/chromium/v8/src/code-stub-assembler.h
@@ -8,6 +8,7 @@
#include <functional>
#include "src/compiler/code-assembler.h"
+#include "src/globals.h"
#include "src/objects.h"
namespace v8 {
@@ -21,8 +22,10 @@ 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) \
@@ -31,6 +34,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(NanValue, Nan) \
V(NullValue, Null) \
V(TheHoleValue, TheHole) \
+ V(TrueValue, True) \
V(UndefinedValue, Undefined)
// Provides JavaScript-specific "macro-assembler" functionality on top of the
@@ -38,7 +42,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
// it's possible to add JavaScript-specific useful CodeAssembler "macros"
// without modifying files in the compiler directory (and requiring a review
// from a compiler directory OWNER).
-class CodeStubAssembler : public compiler::CodeAssembler {
+class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
public:
// Create with CallStub linkage.
// |result_size| specifies the number of results returned by the stub.
@@ -99,6 +103,14 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
+ compiler::Node* IntPtrAddFoldConstants(compiler::Node* left,
+ compiler::Node* right);
+ compiler::Node* IntPtrSubFoldConstants(compiler::Node* left,
+ compiler::Node* right);
+ // Round the 32bits payload of the provided word up to the next power of two.
+ compiler::Node* IntPtrRoundUpToPowerOfTwo32(compiler::Node* value);
+ compiler::Node* IntPtrMax(compiler::Node* left, compiler::Node* right);
+
// Float64 operations.
compiler::Node* Float64Ceil(compiler::Node* x);
compiler::Node* Float64Floor(compiler::Node* x);
@@ -120,9 +132,7 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Smi operations.
compiler::Node* SmiAdd(compiler::Node* a, compiler::Node* b);
- compiler::Node* SmiAddWithOverflow(compiler::Node* a, compiler::Node* b);
compiler::Node* SmiSub(compiler::Node* a, compiler::Node* b);
- compiler::Node* SmiSubWithOverflow(compiler::Node* a, compiler::Node* b);
compiler::Node* SmiEqual(compiler::Node* a, compiler::Node* b);
compiler::Node* SmiAbove(compiler::Node* a, compiler::Node* b);
compiler::Node* SmiAboveOrEqual(compiler::Node* a, compiler::Node* b);
@@ -136,41 +146,51 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Computes a * b for Smi inputs a and b; result is not necessarily a Smi.
compiler::Node* SmiMul(compiler::Node* a, compiler::Node* b);
compiler::Node* SmiOr(compiler::Node* a, compiler::Node* b) {
- return WordOr(a, b);
+ return BitcastWordToTaggedSigned(
+ WordOr(BitcastTaggedToWord(a), BitcastTaggedToWord(b)));
}
+ // Smi | HeapNumber operations.
+ compiler::Node* NumberInc(compiler::Node* value);
+
// Allocate an object of the given size.
compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone);
compiler::Node* Allocate(int size, AllocationFlags flags = kNone);
compiler::Node* InnerAllocate(compiler::Node* previous, int offset);
compiler::Node* InnerAllocate(compiler::Node* previous,
compiler::Node* offset);
+ compiler::Node* IsRegularHeapObjectSize(compiler::Node* size);
- void Assert(compiler::Node* condition);
+ typedef std::function<compiler::Node*()> ConditionBody;
+ void Assert(ConditionBody condition_body, const char* string = nullptr,
+ const char* file = nullptr, int line = 0);
// Check a value for smi-ness
- compiler::Node* WordIsSmi(compiler::Node* a);
+ compiler::Node* TaggedIsSmi(compiler::Node* a);
// Check that the value is a non-negative smi.
compiler::Node* WordIsPositiveSmi(compiler::Node* a);
+ // Check that a word has a word-aligned address.
+ compiler::Node* WordIsWordAligned(compiler::Node* word);
+ compiler::Node* WordIsPowerOfTwo(compiler::Node* value);
void BranchIfSmiEqual(compiler::Node* a, compiler::Node* b, Label* if_true,
Label* if_false) {
- BranchIf(SmiEqual(a, b), if_true, if_false);
+ Branch(SmiEqual(a, b), if_true, if_false);
}
void BranchIfSmiLessThan(compiler::Node* a, compiler::Node* b, Label* if_true,
Label* if_false) {
- BranchIf(SmiLessThan(a, b), if_true, if_false);
+ Branch(SmiLessThan(a, b), if_true, if_false);
}
void BranchIfSmiLessThanOrEqual(compiler::Node* a, compiler::Node* b,
Label* if_true, Label* if_false) {
- BranchIf(SmiLessThanOrEqual(a, b), if_true, if_false);
+ Branch(SmiLessThanOrEqual(a, b), if_true, if_false);
}
void BranchIfFloat64IsNaN(compiler::Node* value, Label* if_true,
Label* if_false) {
- BranchIfFloat64Equal(value, value, if_false, if_true);
+ Branch(Float64Equal(value, value), if_false, if_true);
}
// Branches to {if_true} if ToBoolean applied to {value} yields true,
@@ -187,6 +207,10 @@ class CodeStubAssembler : public compiler::CodeAssembler {
if_notequal);
}
+ void BranchIfJSReceiver(compiler::Node* object, Label* if_true,
+ Label* if_false);
+ void BranchIfJSObject(compiler::Node* object, Label* if_true,
+ Label* if_false);
void BranchIfFastJSArray(compiler::Node* object, compiler::Node* context,
Label* if_true, Label* if_false);
@@ -222,8 +246,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* LoadMap(compiler::Node* object);
// Load the instance type of an HeapObject.
compiler::Node* LoadInstanceType(compiler::Node* object);
- // Checks that given heap object has given instance type.
- void AssertInstanceType(compiler::Node* object, InstanceType instance_type);
+ // Compare the instance the type of the object against the provided one.
+ compiler::Node* HasInstanceType(compiler::Node* object, InstanceType type);
// Load the properties backing store of a JSObject.
compiler::Node* LoadProperties(compiler::Node* object);
// Load the elements backing store of a JSObject.
@@ -248,6 +272,10 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* LoadMapDescriptors(compiler::Node* map);
// Load the prototype of a map.
compiler::Node* LoadMapPrototype(compiler::Node* map);
+ // Load the prototype info of a map. The result has to be checked if it is a
+ // prototype info object or not.
+ compiler::Node* LoadMapPrototypeInfo(compiler::Node* map,
+ Label* if_has_no_proto_info);
// Load the instance size of a Map.
compiler::Node* LoadMapInstanceSize(compiler::Node* map);
// Load the inobject properties count of a Map (valid only for JSObjects).
@@ -256,6 +284,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* LoadMapConstructorFunctionIndex(compiler::Node* map);
// Load the constructor of a Map (equivalent to Map::GetConstructor()).
compiler::Node* LoadMapConstructor(compiler::Node* map);
+ // Check if the map is set for slow properties.
+ compiler::Node* IsDictionaryMap(compiler::Node* map);
// Load the hash field of a name as an uint32 value.
compiler::Node* LoadNameHashField(compiler::Node* name);
@@ -270,6 +300,7 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Load value field of a JSValue object.
compiler::Node* LoadJSValueValue(compiler::Node* object);
// Load value field of a WeakCell object.
+ compiler::Node* LoadWeakCellValueUnchecked(compiler::Node* weak_cell);
compiler::Node* LoadWeakCellValue(compiler::Node* weak_cell,
Label* if_cleared = nullptr);
@@ -294,9 +325,20 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* LoadDoubleWithHoleCheck(
compiler::Node* base, compiler::Node* offset, Label* if_hole,
MachineType machine_type = MachineType::Float64());
+ compiler::Node* LoadFixedTypedArrayElement(
+ compiler::Node* data_pointer, compiler::Node* index_node,
+ ElementsKind elements_kind,
+ ParameterMode parameter_mode = INTEGER_PARAMETERS);
// Context manipulation
compiler::Node* LoadContextElement(compiler::Node* context, int slot_index);
+ compiler::Node* LoadContextElement(compiler::Node* context,
+ compiler::Node* slot_index);
+ compiler::Node* StoreContextElement(compiler::Node* context, int slot_index,
+ compiler::Node* value);
+ compiler::Node* StoreContextElement(compiler::Node* context,
+ compiler::Node* slot_index,
+ compiler::Node* value);
compiler::Node* LoadNativeContext(compiler::Node* context);
compiler::Node* LoadJSArrayElementsMap(ElementsKind kind,
@@ -324,6 +366,14 @@ class CodeStubAssembler : public compiler::CodeAssembler {
Heap::RootListIndex root);
// 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);
+ }
+
+ compiler::Node* StoreFixedArrayElement(
compiler::Node* object, compiler::Node* index, compiler::Node* value,
WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
ParameterMode parameter_mode = INTEGER_PARAMETERS);
@@ -332,19 +382,27 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* object, compiler::Node* index, compiler::Node* value,
ParameterMode parameter_mode = INTEGER_PARAMETERS);
+ void StoreFieldsNoWriteBarrier(compiler::Node* start_address,
+ compiler::Node* end_address,
+ compiler::Node* value);
+
// Allocate a HeapNumber without initializing its value.
compiler::Node* AllocateHeapNumber(MutableMode mode = IMMUTABLE);
// Allocate a HeapNumber with a specific value.
compiler::Node* AllocateHeapNumberWithValue(compiler::Node* value,
MutableMode mode = IMMUTABLE);
// Allocate a SeqOneByteString with the given length.
- compiler::Node* AllocateSeqOneByteString(int length);
- compiler::Node* AllocateSeqOneByteString(compiler::Node* context,
- compiler::Node* length);
+ compiler::Node* AllocateSeqOneByteString(int length,
+ AllocationFlags flags = kNone);
+ compiler::Node* AllocateSeqOneByteString(
+ compiler::Node* context, compiler::Node* length,
+ ParameterMode mode = INTPTR_PARAMETERS, AllocationFlags flags = kNone);
// Allocate a SeqTwoByteString with the given length.
- compiler::Node* AllocateSeqTwoByteString(int length);
- compiler::Node* AllocateSeqTwoByteString(compiler::Node* context,
- compiler::Node* length);
+ compiler::Node* AllocateSeqTwoByteString(int length,
+ AllocationFlags flags = kNone);
+ compiler::Node* AllocateSeqTwoByteString(
+ compiler::Node* context, compiler::Node* length,
+ ParameterMode mode = INTPTR_PARAMETERS, AllocationFlags flags = kNone);
// Allocate a SlicedOneByteString with the given length, parent and offset.
// |length| and |offset| are expected to be tagged.
@@ -357,6 +415,27 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* parent,
compiler::Node* offset);
+ // Allocate a one-byte ConsString with the given length, first and second
+ // parts. |length| is expected to be tagged, and |first| and |second| are
+ // expected to be one-byte strings.
+ compiler::Node* AllocateOneByteConsString(compiler::Node* length,
+ compiler::Node* first,
+ compiler::Node* second,
+ AllocationFlags flags = kNone);
+ // Allocate a two-byte ConsString with the given length, first and second
+ // parts. |length| is expected to be tagged, and |first| and |second| are
+ // expected to be two-byte strings.
+ compiler::Node* AllocateTwoByteConsString(compiler::Node* length,
+ compiler::Node* first,
+ compiler::Node* second,
+ AllocationFlags flags = kNone);
+
+ // Allocate an appropriate one- or two-byte ConsString with the first and
+ // second parts specified by |first| and |second|.
+ compiler::Node* NewConsString(compiler::Node* context, compiler::Node* length,
+ compiler::Node* left, compiler::Node* right,
+ AllocationFlags flags = kNone);
+
// Allocate a RegExpResult with the given length (the number of captures,
// including the match itself), index (the index where the match starts),
// and input string. |length| and |index| are expected to be tagged, and
@@ -366,6 +445,22 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* index,
compiler::Node* input);
+ compiler::Node* AllocateNameDictionary(int capacity);
+ compiler::Node* AllocateNameDictionary(compiler::Node* capacity);
+
+ compiler::Node* AllocateJSObjectFromMap(compiler::Node* map,
+ compiler::Node* properties = nullptr,
+ compiler::Node* elements = nullptr);
+
+ void InitializeJSObjectFromMap(compiler::Node* object, compiler::Node* map,
+ compiler::Node* size,
+ compiler::Node* properties = nullptr,
+ compiler::Node* elements = nullptr);
+
+ void InitializeJSObjectBody(compiler::Node* object, compiler::Node* map,
+ compiler::Node* size,
+ int start_offset = JSObject::kHeaderSize);
+
// Allocate a JSArray without elements and initialize the header fields.
compiler::Node* AllocateUninitializedJSArrayWithoutElements(
ElementsKind kind, compiler::Node* array_map, compiler::Node* length,
@@ -390,6 +485,17 @@ class CodeStubAssembler : public compiler::CodeAssembler {
ParameterMode mode = INTEGER_PARAMETERS,
AllocationFlags flags = kNone);
+ // Perform CreateArrayIterator (ES6 #sec-createarrayiterator).
+ compiler::Node* CreateArrayIterator(compiler::Node* array,
+ compiler::Node* array_map,
+ compiler::Node* array_type,
+ compiler::Node* context,
+ IterationKind mode);
+
+ compiler::Node* AllocateJSArrayIterator(compiler::Node* array,
+ compiler::Node* array_map,
+ compiler::Node* map);
+
void FillFixedArrayWithValue(ElementsKind kind, compiler::Node* array,
compiler::Node* from_index,
compiler::Node* to_index,
@@ -417,14 +523,20 @@ class CodeStubAssembler : public compiler::CodeAssembler {
ParameterMode mode = INTEGER_PARAMETERS);
// Copies |character_count| elements from |from_string| to |to_string|
- // starting at the |from_index|'th character. |from_index| and
- // |character_count| must be Smis s.t.
- // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length.
+ // starting at the |from_index|'th character. |from_string| and |to_string|
+ // can either be one-byte strings or two-byte strings, although if
+ // |from_string| is two-byte, then |to_string| must be two-byte.
+ // |from_index|, |to_index| and |character_count| must be either Smis or
+ // intptr_ts depending on |mode| s.t. 0 <= |from_index| <= |from_index| +
+ // |character_count| <= from_string.length and 0 <= |to_index| <= |to_index| +
+ // |character_count| <= to_string.length.
void CopyStringCharacters(compiler::Node* from_string,
compiler::Node* to_string,
compiler::Node* from_index,
+ compiler::Node* to_index,
compiler::Node* character_count,
- String::Encoding encoding);
+ String::Encoding from_encoding,
+ String::Encoding to_encoding, ParameterMode mode);
// Loads an element from |array| of |from_kind| elements by given |offset|
// (NOTE: not index!), does a hole check if |if_hole| is provided and
@@ -467,6 +579,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
int base_allocation_size,
compiler::Node* allocation_site);
+ compiler::Node* TryTaggedToFloat64(compiler::Node* value,
+ Label* if_valueisnotnumber);
compiler::Node* TruncateTaggedToFloat64(compiler::Node* context,
compiler::Node* value);
compiler::Node* TruncateTaggedToWord32(compiler::Node* context,
@@ -499,8 +613,31 @@ class CodeStubAssembler : public compiler::CodeAssembler {
char const* method_name);
// Type checks.
+ // Check whether the map is for an object with special properties, such as a
+ // JSProxy or an object with interceptors.
+ compiler::Node* IsSpecialReceiverMap(compiler::Node* map);
+ compiler::Node* IsSpecialReceiverInstanceType(compiler::Node* instance_type);
compiler::Node* IsStringInstanceType(compiler::Node* instance_type);
+ compiler::Node* IsString(compiler::Node* object);
+ compiler::Node* IsJSObject(compiler::Node* object);
+ compiler::Node* IsJSGlobalProxy(compiler::Node* object);
compiler::Node* IsJSReceiverInstanceType(compiler::Node* instance_type);
+ compiler::Node* IsJSReceiver(compiler::Node* object);
+ compiler::Node* IsMap(compiler::Node* object);
+ compiler::Node* IsCallableMap(compiler::Node* map);
+ compiler::Node* IsName(compiler::Node* object);
+ compiler::Node* IsJSValue(compiler::Node* object);
+ compiler::Node* IsJSArray(compiler::Node* object);
+ compiler::Node* IsNativeContext(compiler::Node* object);
+ compiler::Node* IsWeakCell(compiler::Node* object);
+ compiler::Node* IsFixedDoubleArray(compiler::Node* object);
+ compiler::Node* IsHashTable(compiler::Node* object);
+ compiler::Node* IsDictionary(compiler::Node* object);
+ compiler::Node* IsUnseededNumberDictionary(compiler::Node* object);
+
+ // ElementsKind helpers:
+ compiler::Node* IsFastElementsKind(compiler::Node* elements_kind);
+ compiler::Node* IsHoleyFastElementsKind(compiler::Node* elements_kind);
// String helpers.
// Load a character from a String (might flatten a ConsString).
@@ -513,6 +650,20 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* SubString(compiler::Node* context, compiler::Node* string,
compiler::Node* from, compiler::Node* to);
+ // Return a new string object produced by concatenating |first| with |second|.
+ compiler::Node* StringAdd(compiler::Node* context, compiler::Node* first,
+ compiler::Node* second,
+ AllocationFlags flags = kNone);
+
+ // Return the first index >= {from} at which {needle_char} was found in
+ // {string}, or -1 if such an index does not exist. The returned value is
+ // a Smi, {string} is expected to be a String, {needle_char} is an intptr,
+ // and {from} is expected to be tagged.
+ compiler::Node* StringIndexOfChar(compiler::Node* context,
+ compiler::Node* string,
+ compiler::Node* needle_char,
+ compiler::Node* from);
+
compiler::Node* StringFromCodePoint(compiler::Node* codepoint,
UnicodeEncoding encoding);
@@ -520,6 +671,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Convert a String to a Number.
compiler::Node* StringToNumber(compiler::Node* context,
compiler::Node* input);
+ compiler::Node* NumberToString(compiler::Node* context,
+ compiler::Node* input);
// Convert an object to a name.
compiler::Node* ToName(compiler::Node* context, compiler::Node* input);
// Convert a Non-Number object to a Number.
@@ -528,6 +681,16 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Convert any object to a Number.
compiler::Node* ToNumber(compiler::Node* context, compiler::Node* input);
+ // Convert any object to a String.
+ compiler::Node* ToString(compiler::Node* context, compiler::Node* input);
+
+ // Convert any object to a Primitive.
+ compiler::Node* JSReceiverToPrimitive(compiler::Node* context,
+ compiler::Node* input);
+
+ // Convert a String to a flat String.
+ compiler::Node* FlattenString(compiler::Node* string);
+
enum ToIntegerTruncationMode {
kNoTruncation,
kTruncateMinusZero,
@@ -540,20 +703,50 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Returns a node that contains a decoded (unsigned!) value of a bit
// field |T| in |word32|. Returns result as an uint32 node.
template <typename T>
- compiler::Node* BitFieldDecode(compiler::Node* word32) {
- return BitFieldDecode(word32, T::kShift, T::kMask);
+ compiler::Node* DecodeWord32(compiler::Node* word32) {
+ return DecodeWord32(word32, T::kShift, T::kMask);
+ }
+
+ // Returns a node that contains a decoded (unsigned!) value of a bit
+ // field |T| in |word|. Returns result as a word-size node.
+ template <typename T>
+ compiler::Node* DecodeWord(compiler::Node* word) {
+ return DecodeWord(word, T::kShift, T::kMask);
}
// Returns a node that contains a decoded (unsigned!) value of a bit
// field |T| in |word32|. Returns result as a word-size node.
template <typename T>
- compiler::Node* BitFieldDecodeWord(compiler::Node* word32) {
- return ChangeUint32ToWord(BitFieldDecode<T>(word32));
+ compiler::Node* DecodeWordFromWord32(compiler::Node* word32) {
+ return DecodeWord<T>(ChangeUint32ToWord(word32));
}
// Decodes an unsigned (!) value from |word32| to an uint32 node.
- compiler::Node* BitFieldDecode(compiler::Node* word32, uint32_t shift,
- uint32_t mask);
+ compiler::Node* DecodeWord32(compiler::Node* word32, uint32_t shift,
+ uint32_t mask);
+
+ // Decodes an unsigned (!) value from |word| to a word-size node.
+ compiler::Node* DecodeWord(compiler::Node* word, uint32_t shift,
+ uint32_t mask);
+
+ // Returns true if any of the |T|'s bits in given |word32| are set.
+ template <typename T>
+ compiler::Node* IsSetWord32(compiler::Node* word32) {
+ return IsSetWord32(word32, T::kMask);
+ }
+
+ // Returns true if any of the mask's bits in given |word32| are set.
+ compiler::Node* IsSetWord32(compiler::Node* word32, uint32_t mask) {
+ return Word32NotEqual(Word32And(word32, Int32Constant(mask)),
+ Int32Constant(0));
+ }
+
+ // Returns true if any of the |T|'s bits in given |word| are set.
+ template <typename T>
+ compiler::Node* IsSetWord(compiler::Node* word) {
+ return WordNotEqual(WordAnd(word, IntPtrConstant(T::kMask)),
+ IntPtrConstant(0));
+ }
void SetCounter(StatsCounter* counter, int value);
void IncrementCounter(StatsCounter* counter, int delta);
@@ -576,6 +769,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* EntryToIndex(compiler::Node* entry) {
return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
}
+ // Calculate a valid size for the a hash table.
+ compiler::Node* HashTableComputeCapacity(compiler::Node* at_least_space_for);
// 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
@@ -723,6 +918,12 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* feedback, Label* if_handler,
Variable* var_handler, Label* if_miss,
int unroll_count);
+ void HandleKeyedStorePolymorphicCase(compiler::Node* receiver_map,
+ compiler::Node* feedback,
+ Label* if_handler, Variable* var_handler,
+ Label* if_transition_handler,
+ Variable* var_transition_map_cell,
+ Label* if_miss);
compiler::Node* StubCachePrimaryOffset(compiler::Node* name,
compiler::Node* map);
@@ -806,10 +1007,12 @@ class CodeStubAssembler : public compiler::CodeAssembler {
ParameterMode mode, Label* bailout);
void LoadIC(const LoadICParameters* p);
+ void LoadICProtoArray(const LoadICParameters* p, compiler::Node* handler);
void LoadGlobalIC(const LoadICParameters* p);
void KeyedLoadIC(const LoadICParameters* p);
void KeyedLoadICGeneric(const LoadICParameters* p);
void StoreIC(const StoreICParameters* p);
+ void KeyedStoreIC(const StoreICParameters* p, LanguageMode language_mode);
void TransitionElementsKind(compiler::Node* object, compiler::Node* map,
ElementsKind from_kind, ElementsKind to_kind,
@@ -838,14 +1041,110 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* CreateAllocationSiteInFeedbackVector(
compiler::Node* feedback_vector, compiler::Node* slot);
+ enum class IndexAdvanceMode { kPre, kPost };
+
+ void BuildFastLoop(
+ const VariableList& var_list, MachineRepresentation index_rep,
+ compiler::Node* start_index, compiler::Node* end_index,
+ std::function<void(CodeStubAssembler* assembler, compiler::Node* index)>
+ body,
+ int increment, IndexAdvanceMode mode = IndexAdvanceMode::kPre);
+
+ void BuildFastLoop(
+ MachineRepresentation index_rep, compiler::Node* start_index,
+ compiler::Node* end_index,
+ std::function<void(CodeStubAssembler* assembler, compiler::Node* index)>
+ body,
+ int increment, IndexAdvanceMode mode = IndexAdvanceMode::kPre) {
+ BuildFastLoop(VariableList(0, zone()), index_rep, start_index, end_index,
+ body, increment, mode);
+ }
+
+ enum class ForEachDirection { kForward, kReverse };
+
+ void BuildFastFixedArrayForEach(
+ compiler::Node* fixed_array, ElementsKind kind,
+ compiler::Node* first_element_inclusive,
+ compiler::Node* last_element_exclusive,
+ std::function<void(CodeStubAssembler* assembler,
+ compiler::Node* fixed_array, compiler::Node* offset)>
+ body,
+ ParameterMode mode = INTPTR_PARAMETERS,
+ ForEachDirection direction = ForEachDirection::kReverse);
+
+ compiler::Node* GetArrayAllocationSize(compiler::Node* element_count,
+ ElementsKind kind, ParameterMode mode,
+ int header_size) {
+ return ElementOffsetFromIndex(element_count, kind, mode, header_size);
+ }
+
compiler::Node* GetFixedArrayAllocationSize(compiler::Node* element_count,
ElementsKind kind,
ParameterMode mode) {
- return ElementOffsetFromIndex(element_count, kind, mode,
+ return GetArrayAllocationSize(element_count, kind, mode,
FixedArray::kHeaderSize);
}
+ enum RelationalComparisonMode {
+ kLessThan,
+ kLessThanOrEqual,
+ kGreaterThan,
+ kGreaterThanOrEqual
+ };
+
+ compiler::Node* RelationalComparison(RelationalComparisonMode mode,
+ compiler::Node* lhs, compiler::Node* rhs,
+ compiler::Node* context);
+
+ void BranchIfNumericRelationalComparison(RelationalComparisonMode mode,
+ compiler::Node* lhs,
+ compiler::Node* rhs, Label* if_true,
+ Label* if_false);
+
+ void GotoUnlessNumberLessThan(compiler::Node* lhs, compiler::Node* rhs,
+ Label* if_false);
+
+ enum ResultMode { kDontNegateResult, kNegateResult };
+
+ compiler::Node* Equal(ResultMode mode, compiler::Node* lhs,
+ compiler::Node* rhs, compiler::Node* context);
+
+ compiler::Node* StrictEqual(ResultMode mode, compiler::Node* lhs,
+ compiler::Node* rhs, compiler::Node* context);
+
+ // ECMA#sec-samevalue
+ // Similar to StrictEqual except that NaNs are treated as equal and minus zero
+ // differs from positive zero.
+ // Unlike Equal and StrictEqual, returns a value suitable for use in Branch
+ // instructions, e.g. Branch(SameValue(...), &label).
+ compiler::Node* SameValue(compiler::Node* lhs, compiler::Node* rhs,
+ compiler::Node* context);
+
+ compiler::Node* HasProperty(
+ compiler::Node* object, compiler::Node* key, compiler::Node* context,
+ Runtime::FunctionId fallback_runtime_function_id = Runtime::kHasProperty);
+ compiler::Node* ForInFilter(compiler::Node* key, compiler::Node* object,
+ compiler::Node* context);
+
+ compiler::Node* Typeof(compiler::Node* value, compiler::Node* context);
+
+ compiler::Node* InstanceOf(compiler::Node* object, compiler::Node* callable,
+ compiler::Node* context);
+
+ // TypedArray/ArrayBuffer helpers
+ compiler::Node* IsDetachedBuffer(compiler::Node* buffer);
+
+ compiler::Node* ElementOffsetFromIndex(compiler::Node* index,
+ ElementsKind kind, ParameterMode mode,
+ int base_size = 0);
+
+ protected:
+ void HandleStoreICHandlerCase(const StoreICParameters* p,
+ compiler::Node* handler, Label* miss);
+
private:
+ friend class CodeStubArguments;
+
enum ElementSupport { kOnlyProperties, kSupportElements };
void DescriptorLookupLinear(compiler::Node* unique_name,
@@ -861,6 +1160,47 @@ class CodeStubAssembler : public compiler::CodeAssembler {
void HandleLoadICHandlerCase(
const LoadICParameters* p, compiler::Node* handler, Label* miss,
ElementSupport support_elements = kOnlyProperties);
+
+ void HandleLoadICSmiHandlerCase(const LoadICParameters* p,
+ compiler::Node* holder,
+ compiler::Node* smi_handler, Label* miss,
+ ElementSupport support_elements);
+
+ void HandleLoadICProtoHandler(const LoadICParameters* p,
+ compiler::Node* handler, Variable* var_holder,
+ Variable* var_smi_handler,
+ Label* if_smi_handler, Label* miss);
+
+ compiler::Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p,
+ compiler::Node* handler,
+ compiler::Node* handler_length,
+ compiler::Node* handler_flags,
+ Label* miss);
+
+ void CheckPrototype(compiler::Node* prototype_cell, compiler::Node* name,
+ Label* miss);
+
+ void NameDictionaryNegativeLookup(compiler::Node* object,
+ compiler::Node* name, Label* miss);
+
+ // If |transition| is nullptr then the normal field store is generated or
+ // transitioning store otherwise.
+ void HandleStoreFieldAndReturn(compiler::Node* handler_word,
+ compiler::Node* holder,
+ Representation representation,
+ compiler::Node* value,
+ compiler::Node* transition, Label* miss);
+
+ // If |transition| is nullptr then the normal field store is generated or
+ // transitioning store otherwise.
+ void HandleStoreICSmiHandlerCase(compiler::Node* handler_word,
+ compiler::Node* holder,
+ compiler::Node* value,
+ compiler::Node* transition, Label* miss);
+
+ void HandleStoreICProtoHandler(const StoreICParameters* p,
+ compiler::Node* handler, Label* miss);
+
compiler::Node* TryToIntptr(compiler::Node* key, Label* miss);
void EmitFastElementsBoundsCheck(compiler::Node* object,
compiler::Node* elements,
@@ -877,10 +1217,6 @@ class CodeStubAssembler : public compiler::CodeAssembler {
Label* definitely_no_elements,
Label* possibly_elements);
- compiler::Node* ElementOffsetFromIndex(compiler::Node* index,
- ElementsKind kind, ParameterMode mode,
- int base_size = 0);
-
compiler::Node* AllocateRawAligned(compiler::Node* size_in_bytes,
AllocationFlags flags,
compiler::Node* top_address,
@@ -906,9 +1242,83 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* value,
Label* bailout);
+ compiler::Node* AllocateSlicedString(Heap::RootListIndex map_root_index,
+ compiler::Node* length,
+ compiler::Node* parent,
+ compiler::Node* offset);
+
+ compiler::Node* AllocateConsString(Heap::RootListIndex map_root_index,
+ compiler::Node* length,
+ compiler::Node* first,
+ compiler::Node* second,
+ AllocationFlags flags);
+
static const int kElementLoopUnrollThreshold = 8;
};
+class CodeStubArguments {
+ public:
+ // |argc| specifies the number of arguments passed to the builtin excluding
+ // the receiver.
+ CodeStubArguments(CodeStubAssembler* assembler, compiler::Node* argc,
+ CodeStubAssembler::ParameterMode mode =
+ CodeStubAssembler::INTPTR_PARAMETERS);
+
+ compiler::Node* GetReceiver();
+
+ // |index| is zero-based and does not include the receiver
+ compiler::Node* AtIndex(compiler::Node* index,
+ CodeStubAssembler::ParameterMode mode =
+ CodeStubAssembler::INTPTR_PARAMETERS);
+
+ compiler::Node* AtIndex(int index);
+
+ typedef std::function<void(CodeStubAssembler* assembler, compiler::Node* arg)>
+ ForEachBodyFunction;
+
+ // Iteration doesn't include the receiver. |first| and |last| are zero-based.
+ void ForEach(ForEachBodyFunction body, compiler::Node* first = nullptr,
+ compiler::Node* last = nullptr,
+ CodeStubAssembler::ParameterMode mode =
+ CodeStubAssembler::INTPTR_PARAMETERS) {
+ CodeStubAssembler::VariableList list(0, assembler_->zone());
+ ForEach(list, body, first, last);
+ }
+
+ // Iteration doesn't include the receiver. |first| and |last| are zero-based.
+ void ForEach(const CodeStubAssembler::VariableList& vars,
+ ForEachBodyFunction body, compiler::Node* first = nullptr,
+ compiler::Node* last = nullptr,
+ CodeStubAssembler::ParameterMode mode =
+ CodeStubAssembler::INTPTR_PARAMETERS);
+
+ void PopAndReturn(compiler::Node* value);
+
+ private:
+ compiler::Node* GetArguments();
+
+ CodeStubAssembler* assembler_;
+ compiler::Node* argc_;
+ compiler::Node* arguments_;
+ compiler::Node* fp_;
+};
+
+#ifdef DEBUG
+#define CSA_ASSERT(csa, x) \
+ (csa)->Assert([&] { return (x); }, #x, __FILE__, __LINE__)
+#else
+#define CSA_ASSERT(csa, x) ((void)0)
+#endif
+
+#ifdef ENABLE_SLOW_DCHECKS
+#define CSA_SLOW_ASSERT(csa, x) \
+ if (FLAG_enable_slow_asserts) { \
+ (csa)->Assert([&] { return (x); }, #x, __FILE__, __LINE__); \
+ }
+#else
+#define CSA_SLOW_ASSERT(csa, x) ((void)0)
+#endif
+
DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags);
} // namespace internal