1bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Copyright 2016 the V8 project authors. All rights reserved. 2bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// found in the LICENSE file. 4bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/code-stub-assembler.h" 5bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/code-factory.h" 613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/frames-inl.h" 713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/frames.h" 8bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 9bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace v8 { 10bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace internal { 11bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 12bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochusing compiler::Node; 13bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochCodeStubAssembler::CodeStubAssembler(compiler::CodeAssemblerState* state) 1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : compiler::CodeAssembler(state) { 1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (DEBUG_BOOL && FLAG_csa_trap_on_node != nullptr) { 1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HandleBreakOnNode(); 1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 20bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::HandleBreakOnNode() { 2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // FLAG_csa_trap_on_node should be in a form "STUB,NODE" where STUB is a 2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // string specifying the name of a stub and NODE is number specifying node id. 2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* name = state()->name(); 2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size_t name_length = strlen(name); 2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (strncmp(FLAG_csa_trap_on_node, name, name_length) != 0) { 2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Different name. 2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return; 2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size_t option_length = strlen(FLAG_csa_trap_on_node); 3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (option_length < name_length + 2 || 3262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FLAG_csa_trap_on_node[name_length] != ',') { 3362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Option is too short. 3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return; 3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* start = &FLAG_csa_trap_on_node[name_length + 1]; 3762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch char* end; 3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int node_id = static_cast<int>(strtol(start, &end, 10)); 3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (start == end) { 4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Bad node id. 4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return; 4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BreakOnNode(node_id); 4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 45bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::Assert(const NodeGenerator& codition_body, 4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* message, const char* file, 4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int line) { 4913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(DEBUG) 5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (FLAG_debug_code) { 5162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label ok(this); 5262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label not_ok(this, Label::kDeferred); 5362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (message != nullptr && FLAG_code_comments) { 5462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("[ Assert: %s", message); 55c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 5662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("[ Assert"); 5762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* condition = codition_body(); 5962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NOT_NULL(condition); 6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(condition, &ok, ¬_ok); 6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(¬_ok); 6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (message != nullptr) { 6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch char chars[1024]; 6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vector<char> buffer(chars); 6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (file != nullptr) { 6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(buffer, "CSA_ASSERT failed: %s [%s:%d]\n", message, file, 6762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch line); 6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(buffer, "CSA_ASSERT failed: %s\n", message); 7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime( 7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Runtime::kGlobalPrint, SmiConstant(Smi::kZero), 7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HeapConstant(factory()->NewStringFromAsciiChecked(&(buffer[0])))); 74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DebugBreak(); 7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&ok); 7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&ok); 7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("] Assert"); 7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 8013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif 8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 8213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 8362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::Select(Node* condition, const NodeGenerator& true_body, 8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const NodeGenerator& false_body, 8562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineRepresentation rep) { 8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable value(this, rep); 8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label vtrue(this), vfalse(this), end(this); 8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(condition, &vtrue, &vfalse); 8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&vtrue); 9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 9262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value.Bind(true_body()); 9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&end); 9462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 9562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&vfalse); 9662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value.Bind(false_body()); 9862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&end); 9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 10162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&end); 10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value.value(); 10362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 10462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 10562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::SelectConstant(Node* condition, Node* true_value, 10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* false_value, 10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineRepresentation rep) { 10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Select(condition, [=] { return true_value; }, 10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [=] { return false_value; }, rep); 11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::SelectInt32Constant(Node* condition, int true_value, 11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int false_value) { 11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectConstant(condition, Int32Constant(true_value), 11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(false_value), 11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineRepresentation::kWord32); 11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::SelectIntPtrConstant(Node* condition, int true_value, 12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int false_value) { 12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectConstant(condition, IntPtrConstant(true_value), 12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(false_value), 12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::SelectBooleanConstant(Node* condition) { 12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectConstant(condition, TrueConstant(), FalseConstant(), 12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineRepresentation::kTagged); 12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::SelectTaggedConstant(Node* condition, Node* true_value, 13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* false_value) { 13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectConstant(condition, true_value, false_value, 13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineRepresentation::kTagged); 13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::SelectSmiConstant(Node* condition, Smi* true_value, 13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Smi* false_value) { 13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectConstant(condition, SmiConstant(true_value), 14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiConstant(false_value), 14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineRepresentation::kTaggedSigned); 14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::NoContextConstant() { return NumberConstant(0); } 145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#define HEAP_CONSTANT_ACCESSOR(rootName, name) \ 147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* CodeStubAssembler::name##Constant() { \ 148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return LoadRoot(Heap::k##rootName##RootIndex); \ 149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 150f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHEAP_CONSTANT_LIST(HEAP_CONSTANT_ACCESSOR); 151f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#undef HEAP_CONSTANT_ACCESSOR 152bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#define HEAP_CONSTANT_TEST(rootName, name) \ 154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* CodeStubAssembler::Is##name(Node* value) { \ 155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return WordEqual(value, name##Constant()); \ 156f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 157f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHEAP_CONSTANT_LIST(HEAP_CONSTANT_TEST); 158f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#undef HEAP_CONSTANT_TEST 15913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 16013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::HashSeed() { 161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return LoadAndUntagToWord32Root(Heap::kHashSeedRootIndex); 16213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 164bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StaleRegisterConstant() { 165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LoadRoot(Heap::kStaleRegisterRootIndex); 166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 167bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) { 169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (mode == SMI_PARAMETERS) { 170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return SmiConstant(Smi::FromInt(value)); 171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(INTPTR_PARAMETERS, mode); 173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return IntPtrConstant(value); 174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 17762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool CodeStubAssembler::IsIntPtrOrSmiConstantZero(Node* test) { 17862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int32_t constant_test; 17962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Smi* smi_test; 18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if ((ToInt32Constant(test, constant_test) && constant_test == 0) || 18162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (ToSmiConstant(test, smi_test) && smi_test->value() == 0)) { 18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return true; 183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 18462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 185c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IntPtrRoundUpToPowerOfTwo32(Node* value) { 188c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("IntPtrRoundUpToPowerOfTwo32"); 189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, UintPtrLessThanOrEqual(value, IntPtrConstant(0x80000000u))); 190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = IntPtrSub(value, IntPtrConstant(1)); 191c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (int i = 1; i <= 16; i *= 2) { 192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = WordOr(value, WordShr(value, IntPtrConstant(i))); 193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return IntPtrAdd(value, IntPtrConstant(1)); 195c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 196c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 197c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::WordIsPowerOfTwo(Node* value) { 198c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // value && !(value & (value - 1)) 199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordEqual( 20062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Select( 20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch WordEqual(value, IntPtrConstant(0)), 20262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [=] { return IntPtrConstant(1); }, 20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [=] { return WordAnd(value, IntPtrSub(value, IntPtrConstant(1))); }, 20462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()), 205c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(0)); 206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::Float64Round(Node* x) { 209bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* one = Float64Constant(1.0); 210bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* one_half = Float64Constant(0.5); 211bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 212bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label return_x(this); 213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 214bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Round up {x} towards Infinity. 21562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_x(this, MachineRepresentation::kFloat64, Float64Ceil(x)); 216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Float64LessThanOrEqual(Float64Sub(var_x.value(), one_half), x), 218bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &return_x); 219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(var_x.value(), one)); 220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_x); 223bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_x.value(); 224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 226bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::Float64Ceil(Node* x) { 227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IsFloat64RoundUpSupported()) { 228bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Float64RoundUp(x); 229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 231bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* one = Float64Constant(1.0); 232bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* zero = Float64Constant(0.0); 233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* two_52 = Float64Constant(4503599627370496.0E0); 234bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); 235bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 23662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_x(this, MachineRepresentation::kFloat64, x); 237bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label return_x(this), return_minus_x(this); 238bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 239bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if {x} is greater than zero. 240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this); 241bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero, 242bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_xnotgreaterthanzero); 243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 244bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_xgreaterthanzero); 245bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 246bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just return {x} unless it's in the range ]0,2^52[. 247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x); 248bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 249bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Round positive {x} towards Infinity. 250bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52)); 25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64LessThan(var_x.value(), x), &return_x); 252bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Add(var_x.value(), one)); 253bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 255bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 256bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_xnotgreaterthanzero); 257bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just return {x} unless it's in the range ]-2^52,0[ 259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x); 26062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64LessThan(x, zero), &return_x); 261bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 262bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Round negated {x} towards Infinity and return the result negated. 263bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* minus_x = Float64Neg(x); 264bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52)); 26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x); 266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(var_x.value(), one)); 267bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_minus_x); 268bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 269bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 270bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_minus_x); 271bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Neg(var_x.value())); 272bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 273bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 274bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_x); 275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_x.value(); 276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::Float64Floor(Node* x) { 279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IsFloat64RoundDownSupported()) { 280bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Float64RoundDown(x); 281bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 282bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 283bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* one = Float64Constant(1.0); 284bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* zero = Float64Constant(0.0); 285bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* two_52 = Float64Constant(4503599627370496.0E0); 286bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); 287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 28862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_x(this, MachineRepresentation::kFloat64, x); 289bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label return_x(this), return_minus_x(this); 290bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 291bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if {x} is greater than zero. 292bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this); 293bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero, 294bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_xnotgreaterthanzero); 295bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_xgreaterthanzero); 297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 298bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just return {x} unless it's in the range ]0,2^52[. 299bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x); 300bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 301bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Round positive {x} towards -Infinity. 302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52)); 30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64GreaterThan(var_x.value(), x), &return_x); 304bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(var_x.value(), one)); 305bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 307bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_xnotgreaterthanzero); 309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just return {x} unless it's in the range ]-2^52,0[ 311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x); 31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64LessThan(x, zero), &return_x); 313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Round negated {x} towards -Infinity and return the result negated. 315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* minus_x = Float64Neg(x); 316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52)); 31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64LessThan(var_x.value(), minus_x), &return_minus_x); 318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Add(var_x.value(), one)); 319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_minus_x); 320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 321bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 322bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_minus_x); 323bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Neg(var_x.value())); 324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_x); 327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_x.value(); 328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 330c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::Float64RoundToEven(Node* x) { 331c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (IsFloat64RoundTiesEvenSupported()) { 332c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Float64RoundTiesEven(x); 333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 334c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // See ES#sec-touint8clamp for details. 335c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* f = Float64Floor(x); 336c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* f_and_half = Float64Add(f, Float64Constant(0.5)); 337c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 338c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_result(this, MachineRepresentation::kFloat64); 339c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label return_f(this), return_f_plus_one(this), done(this); 340c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 341c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Float64LessThan(f_and_half, x), &return_f_plus_one); 342c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Float64LessThan(x, f_and_half), &return_f); 343c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 344c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* f_mod_2 = Float64Mod(f, Float64Constant(2.0)); 345c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64Equal(f_mod_2, Float64Constant(0.0)), &return_f, 346c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &return_f_plus_one); 347c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 348c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 349c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_f); 350c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(f); 351c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 352c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 353c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_f_plus_one); 354c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(Float64Add(f, Float64Constant(1.0))); 355c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 356c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 357c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 358c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_result.value(); 359c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 360c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 361bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::Float64Trunc(Node* x) { 362bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IsFloat64RoundTruncateSupported()) { 363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Float64RoundTruncate(x); 364bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 365bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 366bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* one = Float64Constant(1.0); 367bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* zero = Float64Constant(0.0); 368bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* two_52 = Float64Constant(4503599627370496.0E0); 369bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); 370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_x(this, MachineRepresentation::kFloat64, x); 372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label return_x(this), return_minus_x(this); 373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if {x} is greater than 0. 375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this); 376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero, 377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_xnotgreaterthanzero); 378bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_xgreaterthanzero); 380bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 381bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IsFloat64RoundDownSupported()) { 382bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64RoundDown(x)); 383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just return {x} unless it's in the range ]0,2^52[. 385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x); 386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Round positive {x} towards -Infinity. 388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52)); 38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64GreaterThan(var_x.value(), x), &return_x); 390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(var_x.value(), one)); 391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 395bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_xnotgreaterthanzero); 396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 397bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IsFloat64RoundUpSupported()) { 398bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64RoundUp(x)); 399bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 400bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just return {x} unless its in the range ]-2^52,0[. 402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x); 40362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64LessThan(x, zero), &return_x); 404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Round negated {x} towards -Infinity and return result negated. 406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* minus_x = Float64Neg(x); 407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52)); 40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x); 409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Sub(var_x.value(), one)); 410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_minus_x); 411bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 413bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_minus_x); 415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_x.Bind(Float64Neg(var_x.value())); 416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_x); 417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_x); 419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_x.value(); 420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 421bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 422f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::SmiShiftBitsConstant() { 423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return IntPtrConstant(kSmiShiftSize + kSmiTagSize); 424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 425f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::SmiFromWord32(Node* value) { 427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch value = ChangeInt32ToIntPtr(value); 428f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return BitcastWordToTaggedSigned(WordShl(value, SmiShiftBitsConstant())); 429bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 431bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::SmiTag(Node* value) { 432bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch int32_t constant_value; 433bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (ToInt32Constant(value, constant_value) && Smi::IsValid(constant_value)) { 434bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return SmiConstant(Smi::FromInt(constant_value)); 435bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 436f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return BitcastWordToTaggedSigned(WordShl(value, SmiShiftBitsConstant())); 437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::SmiUntag(Node* value) { 440f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return WordSar(BitcastTaggedToWord(value), SmiShiftBitsConstant()); 441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::SmiToWord32(Node* value) { 444f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result = SmiUntag(value); 44562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return TruncateWordToWord32(result); 446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 448bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::SmiToFloat64(Node* value) { 449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return ChangeInt32ToFloat64(SmiToWord32(value)); 450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 452f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::SmiMax(Node* a, Node* b) { 45362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectTaggedConstant(SmiLessThan(a, b), b, a); 454f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 455f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 456bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::SmiMin(Node* a, Node* b) { 45762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectTaggedConstant(SmiLessThan(a, b), a, b); 458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::SmiMod(Node* a, Node* b) { 461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); 462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label return_result(this, &var_result), 463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return_minuszero(this, Label::kDeferred), 464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return_nan(this, Label::kDeferred); 465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Untag {a} and {b}. 467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch a = SmiToWord32(a); 468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch b = SmiToWord32(b); 469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Return NaN if {b} is zero. 471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf(Word32Equal(b, Int32Constant(0)), &return_nan); 472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {a} is non-negative. 474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_aisnotnegative(this), if_aisnegative(this, Label::kDeferred); 475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(Int32LessThanOrEqual(Int32Constant(0), a), &if_aisnotnegative, 476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &if_aisnegative); 477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_aisnotnegative); 479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Fast case, don't need to check any other edge cases. 481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* r = Int32Mod(a, b); 482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_result.Bind(SmiFromWord32(r)); 483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_aisnegative); 487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (SmiValuesAre32Bits()) { 489f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {a} is kMinInt and {b} is -1 (only relevant if the 490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // kMinInt is actually representable as a Smi). 491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label join(this); 49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(a, Int32Constant(kMinInt)), &join); 493f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf(Word32Equal(b, Int32Constant(-1)), &return_minuszero); 494f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&join); 495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&join); 496f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 497f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 498f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform the integer modulus operation. 499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* r = Int32Mod(a, b); 500f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {r} is zero, and if so return -0, because we have to 502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // take the sign of the left hand side {a}, which is negative. 503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf(Word32Equal(r, Int32Constant(0)), &return_minuszero); 504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The remainder {r} can be outside the valid Smi range on 32bit 506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // architectures, so we cannot just say SmiFromWord32(r) here. 507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_result.Bind(ChangeInt32ToTagged(r)); 508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&return_minuszero); 512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_result.Bind(MinusZeroConstant()); 513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&return_nan); 516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_result.Bind(NanConstant()); 517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&return_result); 520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return var_result.value(); 521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::SmiMul(Node* a, Node* b) { 524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); 525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable var_lhs_float64(this, MachineRepresentation::kFloat64), 526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_rhs_float64(this, MachineRepresentation::kFloat64); 527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label return_result(this, &var_result); 528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Both {a} and {b} are Smis. Convert them to integers and multiply. 530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* lhs32 = SmiToWord32(a); 531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* rhs32 = SmiToWord32(b); 532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* pair = Int32MulWithOverflow(lhs32, rhs32); 533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* overflow = Projection(1, pair); 535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if the multiplication overflowed. 537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_overflow(this, Label::kDeferred), if_notoverflow(this); 538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(overflow, &if_overflow, &if_notoverflow); 539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_notoverflow); 540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the answer is zero, we may need to return -0.0, depending on the 542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input. 543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label answer_zero(this), answer_not_zero(this); 544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* answer = Projection(0, pair); 545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* zero = Int32Constant(0); 54662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Word32Equal(answer, zero), &answer_zero, &answer_not_zero); 547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&answer_not_zero); 548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_result.Bind(ChangeInt32ToTagged(answer)); 550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&answer_zero); 553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* or_result = Word32Or(lhs32, rhs32); 555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_should_be_negative_zero(this), if_should_be_zero(this); 556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(Int32LessThan(or_result, zero), &if_should_be_negative_zero, 557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &if_should_be_zero); 558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_should_be_negative_zero); 559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_result.Bind(MinusZeroConstant()); 561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_should_be_zero); 564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 56562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(SmiConstant(0)); 566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 567f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_overflow); 571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_lhs_float64.Bind(SmiToFloat64(a)); 573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_rhs_float64.Bind(SmiToFloat64(b)); 574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = Float64Mul(var_lhs_float64.value(), var_rhs_float64.value()); 575c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = AllocateHeapNumberWithValue(value); 576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_result.Bind(result); 577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&return_result); 578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&return_result); 581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return var_result.value(); 582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 58462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::TruncateWordToWord32(Node* value) { 58562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (Is64()) { 58662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return TruncateInt64ToInt32(value); 58762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 58862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 58962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 59062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 591c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::TaggedIsSmi(Node* a) { 592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordEqual(WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)), 593c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(0)); 594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 595bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 59662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::TaggedIsNotSmi(Node* a) { 59762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return WordNotEqual( 59862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)), 59962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(0)); 60062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 60162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 60262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::TaggedIsPositiveSmi(Node* a) { 60362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return WordEqual(WordAnd(BitcastTaggedToWord(a), 60462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(kSmiTagMask | kSmiSignMask)), 605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrConstant(0)); 606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 608c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::WordIsWordAligned(Node* word) { 609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordEqual(IntPtrConstant(0), 610c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch WordAnd(word, IntPtrConstant((1 << kPointerSizeLog2) - 1))); 611c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 612c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 613f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::BranchIfPrototypesHaveNoElements( 614f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* receiver_map, Label* definitely_no_elements, 615f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* possibly_elements) { 61662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_map(this, MachineRepresentation::kTagged, receiver_map); 617f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label loop_body(this, &var_map); 618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* empty_elements = LoadRoot(Heap::kEmptyFixedArrayRootIndex); 619f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&loop_body); 620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 621f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&loop_body); 622f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 623f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* map = var_map.value(); 624f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* prototype = LoadMapPrototype(map); 625f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(WordEqual(prototype, NullConstant()), definitely_no_elements); 626f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* prototype_map = LoadMap(prototype); 627f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pessimistically assume elements if a Proxy, Special API Object, 628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // or JSValue wrapper is found on the prototype chain. After this 629f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // instance type check, it's not necessary to check for interceptors or 630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // access checks. 631f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map), 632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), 633f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch possibly_elements); 634f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(WordNotEqual(LoadElements(prototype), empty_elements), 635f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch possibly_elements); 636f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_map.Bind(prototype_map); 637f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&loop_body); 638f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 639f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid CodeStubAssembler::BranchIfJSReceiver(Node* object, Label* if_true, 642c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* if_false) { 643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(object), if_false); 644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Int32GreaterThanOrEqual(LoadInstanceType(object), 646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(FIRST_JS_RECEIVER_TYPE)), 647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_true, if_false); 648c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 649c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 650c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid CodeStubAssembler::BranchIfJSObject(Node* object, Label* if_true, 651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* if_false) { 652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(object), if_false); 653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 654c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Int32GreaterThanOrEqual(LoadInstanceType(object), 655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(FIRST_JS_OBJECT_TYPE)), 656c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_true, if_false); 657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 65962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::BranchIfFastJSArray( 66062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object, Node* context, CodeStubAssembler::FastJSArrayAccessMode mode, 66162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_true, Label* if_false) { 662f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Bailout if receiver is a Smi. 663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(object), if_false); 664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* map = LoadMap(object); 666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 667f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Bailout if instance type is not JS_ARRAY_TYPE. 66862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32NotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), 669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if_false); 670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* elements_kind = LoadMapElementsKind(map); 672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 673f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Bailout if receiver has slow elements. 67462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsFastElementsKind(elements_kind), if_false); 675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 676f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check prototype chain if receiver does not have packed elements. 67762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode == FastJSArrayAccessMode::INBOUNDS_READ) { 67862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsHoleyFastElementsKind(elements_kind), if_true); 67962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 680f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch BranchIfPrototypesHaveNoElements(map, if_true, if_false); 681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 683bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, 684bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch AllocationFlags flags, 685bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* top_address, 686bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* limit_address) { 687bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* top = Load(MachineType::Pointer(), top_address); 688bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* limit = Load(MachineType::Pointer(), limit_address); 689bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If there's not enough space, call the runtime. 691bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable result(this, MachineRepresentation::kTagged); 692bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label runtime_call(this, Label::kDeferred), no_runtime_call(this); 693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label merge_runtime(this, &result); 694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 69562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (flags & kAllowLargeObjectAllocation) { 69662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this); 69762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsRegularHeapObjectSize(size_in_bytes), &next); 69862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 69962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* runtime_flags = SmiConstant( 70062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Smi::FromInt(AllocateDoubleAlignFlag::encode(false) | 70162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AllocateTargetSpace::encode(AllocationSpace::LO_SPACE))); 70262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const runtime_result = 70362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime(Runtime::kAllocateInTargetSpace, NoContextConstant(), 70462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiTag(size_in_bytes), runtime_flags); 70562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result.Bind(runtime_result); 70662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&merge_runtime); 70762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 70862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 70962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 71062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 711bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* new_top = IntPtrAdd(top, size_in_bytes); 712bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(UintPtrGreaterThanOrEqual(new_top, limit), &runtime_call, 713bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &no_runtime_call); 714bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 715bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&runtime_call); 716bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* runtime_result; 717bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (flags & kPretenured) { 718bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* runtime_flags = SmiConstant( 719bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Smi::FromInt(AllocateDoubleAlignFlag::encode(false) | 720bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch AllocateTargetSpace::encode(AllocationSpace::OLD_SPACE))); 721c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch runtime_result = 722c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallRuntime(Runtime::kAllocateInTargetSpace, NoContextConstant(), 723c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiTag(size_in_bytes), runtime_flags); 724bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 725c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch runtime_result = CallRuntime(Runtime::kAllocateInNewSpace, 726c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch NoContextConstant(), SmiTag(size_in_bytes)); 727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch result.Bind(runtime_result); 729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&merge_runtime); 730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 731bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // When there is enough space, return `top' and bump it up. 732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&no_runtime_call); 733bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* no_runtime_result = top; 734bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address, 735bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch new_top); 736bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch no_runtime_result = BitcastWordToTagged( 737bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrAdd(no_runtime_result, IntPtrConstant(kHeapObjectTag))); 738bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch result.Bind(no_runtime_result); 739bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&merge_runtime); 740bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&merge_runtime); 742bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return result.value(); 743bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 744bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 745bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::AllocateRawAligned(Node* size_in_bytes, 746bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch AllocationFlags flags, 747bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* top_address, 748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* limit_address) { 749bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* top = Load(MachineType::Pointer(), top_address); 750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* limit = Load(MachineType::Pointer(), limit_address); 75162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable adjusted_size(this, MachineType::PointerRepresentation(), 75262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size_in_bytes); 753bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (flags & kDoubleAlignment) { 754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label aligned(this), not_aligned(this), merge(this, &adjusted_size); 755bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(WordAnd(top, IntPtrConstant(kDoubleAlignmentMask)), ¬_aligned, 756bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &aligned); 757bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 758bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(¬_aligned); 759bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* not_aligned_size = 760bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrAdd(size_in_bytes, IntPtrConstant(kPointerSize)); 761bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch adjusted_size.Bind(not_aligned_size); 762bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&merge); 763bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 764bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&aligned); 765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&merge); 766bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 767bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&merge); 768bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 769bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 77062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable address( 77162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch this, MachineRepresentation::kTagged, 77262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AllocateRawUnaligned(adjusted_size.value(), kNone, top, limit)); 773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 774bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label needs_filler(this), doesnt_need_filler(this), 775bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch merge_address(this, &address); 776bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(IntPtrEqual(adjusted_size.value(), size_in_bytes), &doesnt_need_filler, 777bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &needs_filler); 778bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&needs_filler); 780bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Store a filler and increase the address by kPointerSize. 781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreNoWriteBarrier(MachineType::PointerRepresentation(), top, 782bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadRoot(Heap::kOnePointerFillerMapRootIndex)); 783bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch address.Bind(BitcastWordToTagged( 784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrAdd(address.value(), IntPtrConstant(kPointerSize)))); 785bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&merge_address); 786bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 787bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&doesnt_need_filler); 788bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&merge_address); 789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&merge_address); 791bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update the top. 792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address, 793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrAdd(top, adjusted_size.value())); 794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return address.value(); 795bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 797bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::Allocate(Node* size_in_bytes, AllocationFlags flags) { 798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("Allocate"); 799bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch bool const new_space = !(flags & kPretenured); 800bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* top_address = ExternalConstant( 801bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch new_space 802bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ? ExternalReference::new_space_allocation_top_address(isolate()) 803bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch : ExternalReference::old_space_allocation_top_address(isolate())); 80462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(kPointerSize, 80562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalReference::new_space_allocation_limit_address(isolate()) 80662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch .address() - 80762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalReference::new_space_allocation_top_address(isolate()) 80862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch .address()); 80962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(kPointerSize, 81062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalReference::old_space_allocation_limit_address(isolate()) 81162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch .address() - 81262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalReference::old_space_allocation_top_address(isolate()) 81362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch .address()); 81462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* limit_address = IntPtrAdd(top_address, IntPtrConstant(kPointerSize)); 815bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 816bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#ifdef V8_HOST_ARCH_32_BIT 817bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (flags & kDoubleAlignment) { 818bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return AllocateRawAligned(size_in_bytes, flags, top_address, limit_address); 819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 820bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif 821bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 822bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return AllocateRawUnaligned(size_in_bytes, flags, top_address, limit_address); 823bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 824bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 825bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) { 826bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return CodeStubAssembler::Allocate(IntPtrConstant(size_in_bytes), flags); 827bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 828bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 829bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::InnerAllocate(Node* previous, Node* offset) { 83062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return BitcastWordToTagged(IntPtrAdd(BitcastTaggedToWord(previous), offset)); 831bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 832bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 833bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::InnerAllocate(Node* previous, int offset) { 834bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return InnerAllocate(previous, IntPtrConstant(offset)); 835bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 836bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsRegularHeapObjectSize(Node* size) { 838c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return UintPtrLessThanOrEqual(size, 839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(kMaxRegularHeapObjectSize)); 840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true, 843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label* if_false) { 84462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_valueissmi(this), if_valueisnotsmi(this), 84562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_valueisheapnumber(this, Label::kDeferred); 846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 84762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Rule out false {value}. 848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf(WordEqual(value, BooleanConstant(false)), if_false); 849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {value} is a Smi or a HeapObject. 851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); 852f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 853f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_valueissmi); 854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 855f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The {value} is a Smi, only need to check against zero. 856f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BranchIfSmiEqual(value, SmiConstant(0), if_false, if_true); 857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_valueisnotsmi); 860f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 86162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if {value} is the empty string. 86262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsEmptyString(value), if_false); 86362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 864f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The {value} is a HeapObject, load its map. 865f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value_map = LoadMap(value); 866f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 86762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Only null, undefined and document.all have the undetectable bit set, 86862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // so we can return false immediately when that bit is set. 86962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map_bitfield = LoadMapBitField(value_map); 87062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map_undetectable = 87162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32And(value_map_bitfield, Int32Constant(1 << Map::kIsUndetectable)); 872f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 87362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if the {value} is undetectable. 87462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(value_map_undetectable, Int32Constant(0)), if_false); 875f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 87662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We still need to handle numbers specially, but all other {value}s 87762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // that make it here yield true. 87862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(value_map), &if_valueisheapnumber, if_true); 879f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 880f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_valueisheapnumber); 881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 882f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the floating point value of {value}. 883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value_value = LoadObjectField(value, HeapNumber::kValueOffset, 884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MachineType::Float64()); 885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 886f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if the floating point {value} is neither 0.0, -0.0 nor NaN. 887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64LessThan(Float64Constant(0.0), Float64Abs(value_value)), 888c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_true, if_false); 889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 890f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 891f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 89362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::LoadFromFrame(int offset, MachineType rep) { 89413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* frame_pointer = LoadFramePointer(); 89513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return Load(rep, frame_pointer, IntPtrConstant(offset)); 89613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 89713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 89862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::LoadFromParentFrame(int offset, MachineType rep) { 89913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* frame_pointer = LoadParentFramePointer(); 90013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return Load(rep, frame_pointer, IntPtrConstant(offset)); 90113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 90213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 903bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset, 904bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MachineType rep) { 905bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Load(rep, buffer, IntPtrConstant(offset)); 906bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 907bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 908bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadObjectField(Node* object, int offset, 909bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MachineType rep) { 910bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Load(rep, object, IntPtrConstant(offset - kHeapObjectTag)); 911bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 912bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 91313e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadObjectField(Node* object, Node* offset, 91413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch MachineType rep) { 91513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return Load(rep, object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag))); 91613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 91713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 918f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::LoadAndUntagObjectField(Node* object, int offset) { 919f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Is64()) { 920f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_TARGET_LITTLE_ENDIAN 921f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch offset += kPointerSize / 2; 922f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif 923f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ChangeInt32ToInt64( 924f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LoadObjectField(object, offset, MachineType::Int32())); 925f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return SmiToWord(LoadObjectField(object, offset, MachineType::AnyTagged())); 927f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 928f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 929f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 930f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::LoadAndUntagToWord32ObjectField(Node* object, 931f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int offset) { 932f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Is64()) { 933f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_TARGET_LITTLE_ENDIAN 934f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch offset += kPointerSize / 2; 935f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif 936f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return LoadObjectField(object, offset, MachineType::Int32()); 937f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return SmiToWord32( 939f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LoadObjectField(object, offset, MachineType::AnyTagged())); 940f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 941f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::LoadAndUntagSmi(Node* base, int index) { 944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Is64()) { 945f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_TARGET_LITTLE_ENDIAN 946f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch index += kPointerSize / 2; 947f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif 948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ChangeInt32ToInt64( 949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Load(MachineType::Int32(), base, IntPtrConstant(index))); 950f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 951f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return SmiToWord( 952f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Load(MachineType::AnyTagged(), base, IntPtrConstant(index))); 953f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 954f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 955f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 956f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::LoadAndUntagToWord32Root( 957f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Heap::RootListIndex root_index) { 958f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* roots_array_start = 959f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExternalConstant(ExternalReference::roots_array_start(isolate())); 960f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int index = root_index * kPointerSize; 961f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Is64()) { 962f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_TARGET_LITTLE_ENDIAN 963f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch index += kPointerSize / 2; 964f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif 965f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return Load(MachineType::Int32(), roots_array_start, IntPtrConstant(index)); 966f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 967f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return SmiToWord32(Load(MachineType::AnyTagged(), roots_array_start, 968f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch IntPtrConstant(index))); 969f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 970f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 971f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 97262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::StoreAndTagSmi(Node* base, int offset, Node* value) { 97362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (Is64()) { 97462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int zero_offset = offset + kPointerSize / 2; 97562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int payload_offset = offset; 97662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#if V8_TARGET_LITTLE_ENDIAN 97762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch std::swap(zero_offset, payload_offset); 97862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif 97962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, base, 98062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(zero_offset), Int32Constant(0)); 98162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return StoreNoWriteBarrier(MachineRepresentation::kWord32, base, 98262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(payload_offset), 98362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TruncateInt64ToInt32(value)); 98462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 98562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return StoreNoWriteBarrier(MachineRepresentation::kTaggedSigned, base, 98662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(offset), SmiTag(value)); 98762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 98862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 98962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 990bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadHeapNumberValue(Node* object) { 99113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(object, HeapNumber::kValueOffset, 99213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch MachineType::Float64()); 993bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 994bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 995bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadMap(Node* object) { 996bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LoadObjectField(object, HeapObject::kMapOffset); 997bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 998bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 999bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadInstanceType(Node* object) { 1000bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LoadMapInstanceType(LoadMap(object)); 1001bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1003c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::HasInstanceType(Node* object, 1004c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch InstanceType instance_type) { 1005c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Word32Equal(LoadInstanceType(object), Int32Constant(instance_type)); 100613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 100713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 100862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::DoesntHaveInstanceType(Node* object, 100962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch InstanceType instance_type) { 101062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Word32NotEqual(LoadInstanceType(object), Int32Constant(instance_type)); 101162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 101262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 101313e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadProperties(Node* object) { 101413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(object, JSObject::kPropertiesOffset); 101513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 101613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1017bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadElements(Node* object) { 1018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LoadObjectField(object, JSObject::kElementsOffset); 1019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::LoadJSArrayLength(Node* array) { 1022c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsJSArray(array)); 1023f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return LoadObjectField(array, JSArray::kLengthOffset); 1024f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1025f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1026c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) { 1027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LoadObjectField(array, FixedArrayBase::kLengthOffset); 1028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1030f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::LoadAndUntagFixedArrayBaseLength(Node* array) { 1031f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return LoadAndUntagObjectField(array, FixedArrayBase::kLengthOffset); 1032f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1033f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadMapBitField(Node* map) { 1035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 103613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(map, Map::kBitFieldOffset, MachineType::Uint8()); 1037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1039bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadMapBitField2(Node* map) { 1040c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 104113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(map, Map::kBitField2Offset, MachineType::Uint8()); 1042bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1043bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadMapBitField3(Node* map) { 1045c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 104613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(map, Map::kBitField3Offset, MachineType::Uint32()); 1047bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1048bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1049bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadMapInstanceType(Node* map) { 105013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(map, Map::kInstanceTypeOffset, MachineType::Uint8()); 1051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1053f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::LoadMapElementsKind(Node* map) { 1054c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 1055f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* bit_field2 = LoadMapBitField2(map); 1056c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return DecodeWord32<Map::ElementsKindBits>(bit_field2); 1057f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1058f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1059bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadMapDescriptors(Node* map) { 1060c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 1061bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LoadObjectField(map, Map::kDescriptorsOffset); 1062bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1063bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1064bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadMapPrototype(Node* map) { 1065c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LoadObjectField(map, Map::kPrototypeOffset); 1067bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1068bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1069c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::LoadMapPrototypeInfo(Node* map, 1070c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* if_no_proto_info) { 1071c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsMap(map)); 1072c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* prototype_info = 1073c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset); 1074c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(prototype_info), if_no_proto_info); 107562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(WordEqual(LoadMap(prototype_info), 107662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadRoot(Heap::kPrototypeInfoMapRootIndex)), 107762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_no_proto_info); 1078c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return prototype_info; 1079c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1080c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 108113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadMapInstanceSize(Node* map) { 1082c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 1083f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return ChangeUint32ToWord( 1084f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8())); 108513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 108613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 108713e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadMapInobjectProperties(Node* map) { 1088c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 108913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // See Map::GetInObjectProperties() for details. 109013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 1091c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, 1092c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32GreaterThanOrEqual(LoadMapInstanceType(map), 1093c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(FIRST_JS_OBJECT_TYPE))); 1094f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return ChangeUint32ToWord(LoadObjectField( 1095f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset, 1096f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineType::Uint8())); 1097f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1098f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1099f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::LoadMapConstructorFunctionIndex(Node* map) { 1100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 1101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // See Map::GetConstructorFunctionIndex() for details. 1102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); 1103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, Int32LessThanOrEqual(LoadMapInstanceType(map), 1104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(LAST_PRIMITIVE_TYPE))); 1105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return ChangeUint32ToWord(LoadObjectField( 110613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset, 1107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineType::Uint8())); 110813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 110913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::LoadMapConstructor(Node* map) { 1111c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable result(this, MachineRepresentation::kTagged, 111362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(map, Map::kConstructorOrBackPointerOffset)); 1114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label done(this), loop(this, &result); 1116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 1117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&loop); 1118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(result.value()), &done); 1120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* is_map_type = 1121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Word32Equal(LoadInstanceType(result.value()), Int32Constant(MAP_TYPE)); 112262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(is_map_type, &done); 1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch result.Bind( 1124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LoadObjectField(result.value(), Map::kConstructorOrBackPointerOffset)); 1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 1126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&done); 1128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return result.value(); 1129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 113162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::LoadSharedFunctionInfoSpecialField( 113262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* shared, int offset, ParameterMode mode) { 113362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (Is64()) { 113462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = LoadObjectField(shared, offset, MachineType::Int32()); 113562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode == SMI_PARAMETERS) { 113662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = SmiTag(result); 113762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 113862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = ChangeUint32ToWord(result); 113962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 114062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return result; 114162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 114262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = LoadObjectField(shared, offset); 114362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode != SMI_PARAMETERS) { 114462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = SmiUntag(result); 114562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 114662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return result; 114762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 114862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 114962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 115013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadNameHashField(Node* name) { 1151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsName(name)); 115213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32()); 115313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 115413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 115513e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) { 115613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* hash_field = LoadNameHashField(name); 115713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (if_hash_not_computed != nullptr) { 1158f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal( 115913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), 116013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Int32Constant(0)), 116113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_hash_not_computed); 116213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 116313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return Word32Shr(hash_field, Int32Constant(Name::kHashShift)); 116413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 116513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 116613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadStringLength(Node* object) { 1167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsString(object)); 116813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(object, String::kLengthOffset); 116913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 117013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 117113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadJSValueValue(Node* object) { 1172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsJSValue(object)); 117313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return LoadObjectField(object, JSValue::kValueOffset); 117413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 117513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::LoadWeakCellValueUnchecked(Node* weak_cell) { 1177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // TODO(ishell): fix callers. 1178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return LoadObjectField(weak_cell, WeakCell::kValueOffset); 1179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 118113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadWeakCellValue(Node* weak_cell, Label* if_cleared) { 1182c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsWeakCell(weak_cell)); 1183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value = LoadWeakCellValueUnchecked(weak_cell); 118413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (if_cleared != nullptr) { 118513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(WordEqual(value, IntPtrConstant(0)), if_cleared); 118613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 118713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return value; 1188bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1190bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node, 1191bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch int additional_offset, 1192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ParameterMode parameter_mode) { 1193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch int32_t header_size = 1194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FixedArray::kHeaderSize + additional_offset - kHeapObjectTag; 1195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, 1196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch parameter_mode, header_size); 1197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Load(MachineType::AnyTagged(), object, offset); 1198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1199bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1200c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::LoadFixedTypedArrayElement( 1201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* data_pointer, Node* index_node, ElementsKind elements_kind, 1202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ParameterMode parameter_mode) { 1203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset = 1204c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementOffsetFromIndex(index_node, elements_kind, parameter_mode, 0); 1205c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineType type; 1206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (elements_kind) { 1207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT8_ELEMENTS: /* fall through */ 1208c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT8_CLAMPED_ELEMENTS: 1209c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Uint8(); 1210c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1211c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case INT8_ELEMENTS: 1212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Int8(); 1213c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1214c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT16_ELEMENTS: 1215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Uint16(); 1216c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case INT16_ELEMENTS: 1218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Int16(); 1219c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT32_ELEMENTS: 1221c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Uint32(); 1222c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case INT32_ELEMENTS: 1224c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Int32(); 1225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1226c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case FLOAT32_ELEMENTS: 1227c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Float32(); 1228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1229c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case FLOAT64_ELEMENTS: 1230c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch type = MachineType::Float64(); 1231c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 1232c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch default: 1233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch UNREACHABLE(); 1234c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Load(type, data_pointer, offset); 1236c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1237c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement( 1239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* object, Node* index_node, int additional_offset, 1240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ParameterMode parameter_mode) { 1241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int32_t header_size = 1242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FixedArray::kHeaderSize + additional_offset - kHeapObjectTag; 1243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_TARGET_LITTLE_ENDIAN 1244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Is64()) { 1245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch header_size += kPointerSize / 2; 1246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif 1248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, 1249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch parameter_mode, header_size); 1250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Is64()) { 1251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return Load(MachineType::Int32(), object, offset); 1252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return SmiToWord32(Load(MachineType::AnyTagged(), object, offset)); 1254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 125713e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::LoadFixedDoubleArrayElement( 125813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* object, Node* index_node, MachineType machine_type, 1259f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int additional_offset, ParameterMode parameter_mode, Label* if_hole) { 1260c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsFixedDoubleArray(object)); 126113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int32_t header_size = 126213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FixedDoubleArray::kHeaderSize + additional_offset - kHeapObjectTag; 126313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_DOUBLE_ELEMENTS, 126413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch parameter_mode, header_size); 1265f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return LoadDoubleWithHoleCheck(object, offset, if_hole, machine_type); 1266f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1267f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1268f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::LoadDoubleWithHoleCheck(Node* base, Node* offset, 1269f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_hole, 1270f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineType machine_type) { 1271f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (if_hole) { 1272f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(ishell): Compare only the upper part for the hole once the 1273f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // compiler is able to fold addition of already complex |offset| with 1274f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // |kIeeeDoubleExponentWordOffset| into one addressing mode. 1275f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (Is64()) { 1276f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* element = Load(MachineType::Uint64(), base, offset); 1277f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word64Equal(element, Int64Constant(kHoleNanInt64)), if_hole); 1278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* element_upper = Load( 1280f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineType::Uint32(), base, 1281f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrAdd(offset, IntPtrConstant(kIeeeDoubleExponentWordOffset))); 1282f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), 1283f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_hole); 1284f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1285f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1286f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (machine_type.IsNone()) { 1287f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This means the actual value is not needed. 1288f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return nullptr; 1289f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1290f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return Load(machine_type, base, offset); 1291f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1292f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1293f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::LoadContextElement(Node* context, int slot_index) { 1294f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int offset = Context::SlotOffset(slot_index); 1295f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return Load(MachineType::AnyTagged(), context, IntPtrConstant(offset)); 1296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1298c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::LoadContextElement(Node* context, Node* slot_index) { 1299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset = 1300c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrAdd(WordShl(slot_index, kPointerSizeLog2), 1301c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(Context::kHeaderSize - kHeapObjectTag)); 1302c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Load(MachineType::AnyTagged(), context, offset); 1303c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1304c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1305c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::StoreContextElement(Node* context, int slot_index, 1306c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value) { 1307c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int offset = Context::SlotOffset(slot_index); 130862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Store(context, IntPtrConstant(offset), value); 1309c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1311c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::StoreContextElement(Node* context, Node* slot_index, 1312c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value) { 1313c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset = 1314c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrAdd(WordShl(slot_index, kPointerSizeLog2), 1315c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(Context::kHeaderSize - kHeapObjectTag)); 131662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Store(context, offset, value); 131762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 131862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 131962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::StoreContextElementNoWriteBarrier(Node* context, 132062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int slot_index, 132162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value) { 132262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int offset = Context::SlotOffset(slot_index); 132362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return StoreNoWriteBarrier(MachineRepresentation::kTagged, context, 132462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(offset), value); 1325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1326c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadNativeContext(Node* context) { 1328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return LoadContextElement(context, Context::NATIVE_CONTEXT_INDEX); 1329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1330bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind, 1332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* native_context) { 1333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsNativeContext(native_context)); 133462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadContextElement(native_context, Context::ArrayMapIndex(kind)); 1335bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1336bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1337bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) { 1338f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return StoreObjectFieldNoWriteBarrier(object, HeapNumber::kValueOffset, value, 1339f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineRepresentation::kFloat64); 1340bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1342bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StoreObjectField( 1343bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object, int offset, Node* value) { 134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NE(HeapObject::kMapOffset, offset); // Use StoreMap instead. 134562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Store(object, IntPtrConstant(offset - kHeapObjectTag), value); 1346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1348f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::StoreObjectField(Node* object, Node* offset, 1349f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value) { 1350f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int const_offset; 1351f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (ToInt32Constant(offset, const_offset)) { 1352f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return StoreObjectField(object, const_offset, value); 1353f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 135462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Store(object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)), 135562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value); 1356f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1358bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StoreObjectFieldNoWriteBarrier( 1359bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object, int offset, Node* value, MachineRepresentation rep) { 1360bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return StoreNoWriteBarrier(rep, object, 1361bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrConstant(offset - kHeapObjectTag), value); 1362bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1364f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::StoreObjectFieldNoWriteBarrier( 1365f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* object, Node* offset, Node* value, MachineRepresentation rep) { 1366f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int const_offset; 1367f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (ToInt32Constant(offset, const_offset)) { 1368f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return StoreObjectFieldNoWriteBarrier(object, const_offset, value, rep); 1369f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1370f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return StoreNoWriteBarrier( 1371f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch rep, object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)), value); 1372f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 137462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::StoreMap(Node* object, Node* map) { 137562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 137662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return StoreWithMapWriteBarrier( 137762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch object, IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag), map); 137862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 137962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 138062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::StoreMapNoWriteBarrier( 138162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object, Heap::RootListIndex map_root_index) { 138262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return StoreMapNoWriteBarrier(object, LoadRoot(map_root_index)); 138362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 138462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StoreMapNoWriteBarrier(Node* object, Node* map) { 138662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 1387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return StoreNoWriteBarrier( 1388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MachineRepresentation::kTagged, object, 138962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag), map); 1390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::StoreObjectFieldRoot(Node* object, int offset, 1393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Heap::RootListIndex root_index) { 1394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Heap::RootIsImmortalImmovable(root_index)) { 1395f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return StoreObjectFieldNoWriteBarrier(object, offset, LoadRoot(root_index)); 1396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return StoreObjectField(object, offset, LoadRoot(root_index)); 1398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StoreFixedArrayElement(Node* object, Node* index_node, 1402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value, 1403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch WriteBarrierMode barrier_mode, 140462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int additional_offset, 1405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ParameterMode parameter_mode) { 1406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(barrier_mode == SKIP_WRITE_BARRIER || 1407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch barrier_mode == UPDATE_WRITE_BARRIER); 140862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int header_size = 140962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FixedArray::kHeaderSize + additional_offset - kHeapObjectTag; 141062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, 141162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch parameter_mode, header_size); 1412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (barrier_mode == SKIP_WRITE_BARRIER) { 141362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return StoreNoWriteBarrier(MachineRepresentation::kTagged, object, offset, 141462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value); 1415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 141662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Store(object, offset, value); 1417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 1418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StoreFixedDoubleArrayElement( 1421bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { 1422c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsFixedDoubleArray(object)); 1423bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* offset = 1424bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode, 1425bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FixedArray::kHeaderSize - kHeapObjectTag); 1426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MachineRepresentation rep = MachineRepresentation::kFloat64; 1427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return StoreNoWriteBarrier(rep, object, offset, value); 1428bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1429bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 143062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, 143162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* array, 143262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeStubArguments& args, 143362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable& arg_index, 143462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* bailout) { 143562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); 143662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label pre_bailout(this); 143762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label success(this); 143862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_tagged_length(this, MachineRepresentation::kTagged); 143962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterMode mode = OptimalParameterMode(); 144062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_length(this, OptimalParameterRepresentation(), 144162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TaggedToParameter(LoadJSArrayLength(array), mode)); 144262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_elements(this, MachineRepresentation::kTagged, 144362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadElements(array)); 144462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* capacity = 144562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode); 144662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 144762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Resize the capacity of the fixed array if it doesn't fit. 144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label fits(this, &var_elements); 144962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* first = arg_index.value(); 145062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* growth = IntPtrSub(args.GetLength(), first); 145162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_length = 145262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode); 145362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); 145462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); 145562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind, 145662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch kind, capacity, new_capacity, mode, 145762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &pre_bailout)); 145862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&fits); 145962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&fits); 146062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* elements = var_elements.value(); 146162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Push each argument onto the end of the array now that there is enough 146362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // capacity. 146462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeStubAssembler::VariableList push_vars({&var_length}, zone()); 146562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch args.ForEach( 146662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch push_vars, 146762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { 146862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsFastSmiElementsKind(kind)) { 146962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsNotSmi(arg), &pre_bailout); 147062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (IsFastDoubleElementsKind(kind)) { 147162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNotNumber(arg, &pre_bailout); 147262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 147362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsFastDoubleElementsKind(kind)) { 147462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* double_value = ChangeNumberToFloat64(arg); 147562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedDoubleArrayElement(elements, var_length.value(), 147662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Float64SilenceNaN(double_value), mode); 147762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 147862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind) 147962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? SKIP_WRITE_BARRIER 148062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : UPDATE_WRITE_BARRIER; 148162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(elements, var_length.value(), arg, 148262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch barrier_mode, 0, mode); 148362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 148462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Increment(var_length, 1, mode); 148562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }, 148662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch first, nullptr); 148762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 148862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* length = ParameterToTagged(var_length.value(), mode); 148962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_tagged_length.Bind(length); 149062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); 149162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&success); 149262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 149462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&pre_bailout); 149562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 149662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* length = ParameterToTagged(var_length.value(), mode); 149762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_tagged_length.Bind(length); 149862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* diff = SmiSub(length, LoadJSArrayLength(array)); 149962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); 150062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); 150162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(bailout); 150262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 150362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 150462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&success); 150562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return var_tagged_length.value(); 150662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 150762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1508f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { 1509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* result = Allocate(HeapNumber::kSize, kNone); 1510f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Heap::RootListIndex heap_map_index = 1511f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex 1512f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch : Heap::kMutableHeapNumberMapRootIndex; 151362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, heap_map_index); 1514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return result; 1515bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1516bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1517f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, 1518f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MutableMode mode) { 1519f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result = AllocateHeapNumber(mode); 1520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreHeapNumberValue(result, value); 1521bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return result; 1522bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1524c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateSeqOneByteString(int length, 1525c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 1526c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("AllocateSeqOneByteString"); 152762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (length == 0) { 152862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadRoot(Heap::kempty_stringRootIndex); 152962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1530c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = Allocate(SeqOneByteString::SizeFor(length), flags); 1531c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex)); 153262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex); 1533bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, 1534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SmiConstant(Smi::FromInt(length))); 153562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Initialize both used and unused parts of hash field slot at once. 153662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot, 153713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IntPtrConstant(String::kEmptyHashField), 153862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 1539bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return result; 1540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, 1543c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ParameterMode mode, 1544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 1545c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("AllocateSeqOneByteString"); 154613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); 154713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 154813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Compute the SeqOneByteString size and check if it fits into new space. 154962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_lengthiszero(this), if_sizeissmall(this), 155062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_notsizeissmall(this, Label::kDeferred), if_join(this); 155162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero); 155262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* raw_size = GetArrayAllocationSize( 1554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch length, UINT8_ELEMENTS, mode, 1555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SeqOneByteString::kHeaderSize + kObjectAlignmentMask); 1556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); 1557f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 155813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_sizeissmall, &if_notsizeissmall); 155913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 156013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_sizeissmall); 156113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 156213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Just allocate the SeqOneByteString in new space. 1563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = Allocate(size, flags); 1564c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex)); 156562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex); 156662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, 156762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterToTagged(length, mode)); 156862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Initialize both used and unused parts of hash field slot at once. 156962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot, 157013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IntPtrConstant(String::kEmptyHashField), 157162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 157213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_result.Bind(result); 157313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_join); 157413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 157513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 157613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_notsizeissmall); 157713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 157813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // We might need to allocate in large object space, go to the runtime. 157962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context, 158062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterToTagged(length, mode)); 158113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_result.Bind(result); 158213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_join); 158313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 158413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 158562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_lengthiszero); 158662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 158762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); 158862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&if_join); 158962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 159062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 159113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_join); 159213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return var_result.value(); 159313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 159413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateSeqTwoByteString(int length, 1596c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 1597c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("AllocateSeqTwoByteString"); 159862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (length == 0) { 159962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadRoot(Heap::kempty_stringRootIndex); 160062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1601c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags); 1602c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex)); 160362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex); 1604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, 1605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SmiConstant(Smi::FromInt(length))); 160662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Initialize both used and unused parts of hash field slot at once. 160762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot, 160813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IntPtrConstant(String::kEmptyHashField), 160962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 1610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return result; 1611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, 1614c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ParameterMode mode, 1615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 1616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("AllocateSeqTwoByteString"); 161713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); 161813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 161913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Compute the SeqTwoByteString size and check if it fits into new space. 162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_lengthiszero(this), if_sizeissmall(this), 162162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_notsizeissmall(this, Label::kDeferred), if_join(this); 162262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero); 162362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* raw_size = GetArrayAllocationSize( 1625c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch length, UINT16_ELEMENTS, mode, 1626c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SeqOneByteString::kHeaderSize + kObjectAlignmentMask); 1627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); 1628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), 162913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_sizeissmall, &if_notsizeissmall); 163013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 163113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_sizeissmall); 163213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 163313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Just allocate the SeqTwoByteString in new space. 1634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = Allocate(size, flags); 1635c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex)); 163662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex); 1637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier( 1638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result, SeqTwoByteString::kLengthOffset, 1639c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mode == SMI_PARAMETERS ? length : SmiFromWord(length)); 164062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Initialize both used and unused parts of hash field slot at once. 164162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot, 164213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IntPtrConstant(String::kEmptyHashField), 164362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 164413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_result.Bind(result); 164513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_join); 164613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 164713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 164813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_notsizeissmall); 164913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 165013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // We might need to allocate in large object space, go to the runtime. 1651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = 1652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallRuntime(Runtime::kAllocateSeqTwoByteString, context, 1653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mode == SMI_PARAMETERS ? length : SmiFromWord(length)); 165413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_result.Bind(result); 165513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_join); 165613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 165713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 165862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_lengthiszero); 165962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 166062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); 166162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&if_join); 166262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 166362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 166413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_join); 166513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return var_result.value(); 166613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 166713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateSlicedString( 1669c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Heap::RootListIndex map_root_index, Node* length, Node* parent, 1670c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset) { 1671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, TaggedIsSmi(length)); 1672f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result = Allocate(SlicedString::kSize); 1673c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(map_root_index)); 167462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, map_root_index); 1675f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(result, SlicedString::kLengthOffset, length, 1676f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineRepresentation::kTagged); 167762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Initialize both used and unused parts of hash field slot at once. 167862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldSlot, 167962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(String::kEmptyHashField), 168062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 1681f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent, 1682f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineRepresentation::kTagged); 1683f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset, 1684f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineRepresentation::kTagged); 1685f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return result; 1686f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1688c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateSlicedOneByteString(Node* length, Node* parent, 1689c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset) { 1690c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return AllocateSlicedString(Heap::kSlicedOneByteStringMapRootIndex, length, 1691c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch parent, offset); 1692c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1693c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::AllocateSlicedTwoByteString(Node* length, Node* parent, 1695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* offset) { 1696c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return AllocateSlicedString(Heap::kSlicedStringMapRootIndex, length, parent, 1697c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch offset); 1698c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1699c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1700c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateConsString(Heap::RootListIndex map_root_index, 1701c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* length, Node* first, 1702c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* second, 1703c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 1704c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, TaggedIsSmi(length)); 1705c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = Allocate(ConsString::kSize, flags); 1706c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(map_root_index)); 170762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, map_root_index); 1708c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length, 1709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineRepresentation::kTagged); 171062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Initialize both used and unused parts of hash field slot at once. 171162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldSlot, 171262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(String::kEmptyHashField), 171362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 1714c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool const new_space = !(flags & kPretenured); 1715c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (new_space) { 1716c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first, 1717c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineRepresentation::kTagged); 1718c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second, 1719c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineRepresentation::kTagged); 1720c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 1721c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectField(result, ConsString::kFirstOffset, first); 1722c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectField(result, ConsString::kSecondOffset, second); 1723c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1724f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return result; 1725f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1726f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1727c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateOneByteConsString(Node* length, Node* first, 1728c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* second, 1729c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 1730c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return AllocateConsString(Heap::kConsOneByteStringMapRootIndex, length, first, 1731c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch second, flags); 1732c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1733c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1734c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateTwoByteConsString(Node* length, Node* first, 1735c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* second, 1736c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 1737c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return AllocateConsString(Heap::kConsStringMapRootIndex, length, first, 1738c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch second, flags); 1739c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1740c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1741c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::NewConsString(Node* context, Node* length, Node* left, 1742c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* right, AllocationFlags flags) { 1743c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, TaggedIsSmi(length)); 1744c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Added string can be a cons string. 1745c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("Allocating ConsString"); 1746c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* left_instance_type = LoadInstanceType(left); 1747c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* right_instance_type = LoadInstanceType(right); 1748c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1749c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Compute intersection and difference of instance types. 175062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* anded_instance_types = 175162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32And(left_instance_type, right_instance_type); 175262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* xored_instance_types = 175362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32Xor(left_instance_type, right_instance_type); 1754c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1755c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We create a one-byte cons string if 1756c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 1. both strings are one-byte, or 1757c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 2. at least one of the strings is two-byte, but happens to contain only 1758c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // one-byte characters. 1759c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // To do this, we check 1760c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 1. if both strings are one-byte, or if the one-byte data hint is set in 1761c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // both strings, or 1762c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 2. if one of the strings has the one-byte data hint set and the other 1763c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // string is one-byte. 1764c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(kOneByteStringTag != 0); 1765c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(kOneByteDataHintTag != 0); 1766c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label one_byte_map(this); 1767c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label two_byte_map(this); 1768c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 1769c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this, &result); 177062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32NotEqual(Word32And(anded_instance_types, 177162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kStringEncodingMask | 177262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch kOneByteDataHintTag)), 177362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(0)), 1774c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &one_byte_map); 177562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Word32NotEqual(Word32And(xored_instance_types, 177662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kStringEncodingMask | 177762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch kOneByteDataHintMask)), 177862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kOneByteStringTag | kOneByteDataHintTag)), 1779c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &two_byte_map, &one_byte_map); 1780c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1781c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&one_byte_map); 1782c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("One-byte ConsString"); 1783c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(AllocateOneByteConsString(length, left, right, flags)); 1784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 1785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1786c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&two_byte_map); 1787c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("Two-byte ConsString"); 1788c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(AllocateTwoByteConsString(length, left, right, flags)); 1789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 1790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 1792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 1794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1795c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1796f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length, 1797f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* index, Node* input) { 1798f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const max_length = 1799f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray)); 1800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, SmiLessThanOrEqual(length, max_length)); 1801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch USE(max_length); 1802f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1803f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Allocate the JSRegExpResult. 1804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove 1805f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // unneeded store of elements. 1806f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const result = Allocate(JSRegExpResult::kSize); 1807f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1808f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(jgruber): Store map as Heap constant? 1809f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const native_context = LoadNativeContext(context); 1810f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const map = 1811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); 1812f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreMapNoWriteBarrier(result, map); 1813f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1814f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Initialize the header before allocating the elements. 1815f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const empty_array = EmptyFixedArrayConstant(); 1816f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(Heap::RootIsImmortalImmovable(Heap::kEmptyFixedArrayRootIndex)); 1817f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(result, JSArray::kPropertiesOffset, 1818f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch empty_array); 1819f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset, empty_array); 1820f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(result, JSArray::kLengthOffset, length); 1821f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1822f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(result, JSRegExpResult::kIndexOffset, index); 1823f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectField(result, JSRegExpResult::kInputOffset, input); 1824bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1825f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const zero = IntPtrConstant(0); 1826f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const length_intptr = SmiUntag(length); 1827f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const ElementsKind elements_kind = FAST_ELEMENTS; 182813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 182962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const elements = AllocateFixedArray(elements_kind, length_intptr); 1830f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectField(result, JSArray::kElementsOffset, elements); 1831f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1832f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Fill in the elements with undefined. 1833f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FillFixedArrayWithValue(elements_kind, elements, zero, length_intptr, 183462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kUndefinedValueRootIndex); 1835f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1836f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return result; 1837f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1838f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateNameDictionary(int at_least_space_for) { 1840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return AllocateNameDictionary(IntPtrConstant(at_least_space_for)); 1841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1843c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateNameDictionary(Node* at_least_space_for) { 1844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, UintPtrLessThanOrEqual( 1845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch at_least_space_for, 1846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(NameDictionary::kMaxCapacity))); 1847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* capacity = HashTableComputeCapacity(at_least_space_for); 1849c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, WordIsPowerOfTwo(capacity)); 1850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* length = EntryToIndex<NameDictionary>(capacity); 1852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* store_size = 185362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrAdd(WordShl(length, IntPtrConstant(kPointerSizeLog2)), 185462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(NameDictionary::kHeaderSize)); 1855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* result = Allocate(store_size); 1857c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("Initialize NameDictionary"); 1858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Initialize FixedArray fields. 185962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(Heap::kHashTableMapRootIndex)); 186062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, Heap::kHashTableMapRootIndex); 1861c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset, 1862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiFromWord(length)); 1863c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Initialized HashTable fields. 1864c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* zero = SmiConstant(0); 1865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreFixedArrayElement(result, NameDictionary::kNumberOfElementsIndex, zero, 1866c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SKIP_WRITE_BARRIER); 1867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreFixedArrayElement(result, NameDictionary::kNumberOfDeletedElementsIndex, 1868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch zero, SKIP_WRITE_BARRIER); 1869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreFixedArrayElement(result, NameDictionary::kCapacityIndex, 1870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiTag(capacity), SKIP_WRITE_BARRIER); 1871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Initialize Dictionary fields. 1872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* filler = LoadRoot(Heap::kUndefinedValueRootIndex); 1873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreFixedArrayElement(result, NameDictionary::kMaxNumberKeyIndex, filler, 1874c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SKIP_WRITE_BARRIER); 1875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreFixedArrayElement(result, NameDictionary::kNextEnumerationIndexIndex, 1876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiConstant(PropertyDetails::kInitialIndex), 1877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SKIP_WRITE_BARRIER); 1878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Initialize NameDictionary elements. 188062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result_word = BitcastTaggedToWord(result); 1881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* start_address = IntPtrAdd( 188262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result_word, IntPtrConstant(NameDictionary::OffsetOfElementAt( 188362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NameDictionary::kElementsStartIndex) - 188462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch kHeapObjectTag)); 1885c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* end_address = IntPtrAdd( 188662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result_word, IntPtrSub(store_size, IntPtrConstant(kHeapObjectTag))); 1887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreFieldsNoWriteBarrier(start_address, end_address, filler); 1888c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result; 1889c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1891c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::AllocateJSObjectFromMap(Node* map, Node* properties, 189262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* elements, 189362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AllocationFlags flags) { 1894c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsMap(map)); 1895c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* size = 1896c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrMul(LoadMapInstanceSize(map), IntPtrConstant(kPointerSize)); 1897c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsRegularHeapObjectSize(size)); 189862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object = Allocate(size, flags); 1899c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreMapNoWriteBarrier(object, map); 1900c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch InitializeJSObjectFromMap(object, map, size, properties, elements); 1901c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return object; 1902c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1903c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1904c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid CodeStubAssembler::InitializeJSObjectFromMap(Node* object, Node* map, 1905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* size, Node* properties, 1906c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* elements) { 1907c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // This helper assumes that the object is in new-space, as guarded by the 1908c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // check in AllocatedJSObjectFromMap. 1909c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (properties == nullptr) { 1910c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, Word32BinaryNot(IsDictionaryMap((map)))); 1911c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldRoot(object, JSObject::kPropertiesOffset, 1912c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Heap::kEmptyFixedArrayRootIndex); 1913c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 1914c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOffset, 1915c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch properties); 1916c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1917c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (elements == nullptr) { 1918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldRoot(object, JSObject::kElementsOffset, 1919c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Heap::kEmptyFixedArrayRootIndex); 1920c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 1921c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(object, JSObject::kElementsOffset, elements); 1922c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1923c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch InitializeJSObjectBody(object, map, size, JSObject::kHeaderSize); 1924c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1925c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1926c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid CodeStubAssembler::InitializeJSObjectBody(Node* object, Node* map, 1927c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* size, int start_offset) { 1928c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // TODO(cbruni): activate in-object slack tracking machinery. 1929c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("InitializeJSObjectBody"); 1930c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* filler = LoadRoot(Heap::kUndefinedValueRootIndex); 1931c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Calculate the untagged field addresses. 193262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch object = BitcastTaggedToWord(object); 1933c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* start_address = 1934c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrAdd(object, IntPtrConstant(start_offset - kHeapObjectTag)); 1935c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* end_address = 1936c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrSub(IntPtrAdd(object, size), IntPtrConstant(kHeapObjectTag)); 1937c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreFieldsNoWriteBarrier(start_address, end_address, filler); 1938c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1939c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1940c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid CodeStubAssembler::StoreFieldsNoWriteBarrier(Node* start_address, 1941c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* end_address, 1942c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value) { 1943c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("StoreFieldsNoWriteBarrier"); 1944c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, WordIsWordAligned(start_address)); 1945c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, WordIsWordAligned(end_address)); 194662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BuildFastLoop(start_address, end_address, 194762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [this, value](Node* current) { 194862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kTagged, current, 194962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value); 195062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }, 195162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch kPointerSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); 1952c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1953c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1954f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::AllocateUninitializedJSArrayWithoutElements( 1955f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind kind, Node* array_map, Node* length, Node* allocation_site) { 1956f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("begin allocation of JSArray without elements"); 1957f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int base_size = JSArray::kSize; 1958bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (allocation_site != nullptr) { 1959bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch base_size += AllocationMemento::kSize; 1960bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 1961bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* size = IntPtrConstant(base_size); 1963f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* array = AllocateUninitializedJSArray(kind, array_map, length, 1964f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch allocation_site, size); 1965f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return array; 1966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1967bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstd::pair<Node*, Node*> 1969f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochCodeStubAssembler::AllocateUninitializedJSArrayWithElements( 1970f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind kind, Node* array_map, Node* length, Node* allocation_site, 1971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* capacity, ParameterMode capacity_mode) { 1972f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("begin allocation of JSArray with elements"); 1973f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int base_size = JSArray::kSize; 1974f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (allocation_site != nullptr) { 1976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base_size += AllocationMemento::kSize; 1977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1978f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int elements_offset = base_size; 1980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1981f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Compute space for elements 1982f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base_size += FixedArray::kHeaderSize; 1983f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* size = ElementOffsetFromIndex(capacity, kind, capacity_mode, base_size); 1984f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1985f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* array = AllocateUninitializedJSArray(kind, array_map, length, 1986f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch allocation_site, size); 1987f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 198862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* elements = InnerAllocate(array, elements_offset); 198962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(array, JSObject::kElementsOffset, elements); 1990f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1991f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return {array, elements}; 1992f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1993f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1994f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::AllocateUninitializedJSArray(ElementsKind kind, 1995f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* array_map, 1996f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* length, 1997f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* allocation_site, 1998f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* size_in_bytes) { 1999f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* array = Allocate(size_in_bytes); 2000f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2001f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("write JSArray headers"); 2002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreMapNoWriteBarrier(array, array_map); 2003f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 200462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, TaggedIsSmi(length)); 2005f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); 2006f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2007f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldRoot(array, JSArray::kPropertiesOffset, 2008f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Heap::kEmptyFixedArrayRootIndex); 2009bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (allocation_site != nullptr) { 2011bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch InitializeAllocationMemento(array, JSArray::kSize, allocation_site); 2012bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2013f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return array; 2014f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::AllocateJSArray(ElementsKind kind, Node* array_map, 2017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* capacity, Node* length, 2018f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* allocation_site, 2019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ParameterMode capacity_mode) { 202062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node *array = nullptr, *elements = nullptr; 202162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsIntPtrOrSmiConstantZero(capacity)) { 202262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Array is empty. Use the shared empty fixed array instead of allocating a 202362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // new one. 202462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch array = AllocateUninitializedJSArrayWithoutElements(kind, array_map, length, 202562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch nullptr); 202662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldRoot(array, JSArray::kElementsOffset, 202762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kEmptyFixedArrayRootIndex); 202862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 202962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Allocate both array and elements object, and initialize the JSArray. 203062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( 203162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch kind, array_map, length, allocation_site, capacity, capacity_mode); 203262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Setup elements object. 203362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::RootListIndex elements_map_index = 203462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IsFastDoubleElementsKind(kind) ? Heap::kFixedDoubleArrayMapRootIndex 203562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : Heap::kFixedArrayMapRootIndex; 203662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(elements_map_index)); 203762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(elements, elements_map_index); 203862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, 203962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterToTagged(capacity, capacity_mode)); 204062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Fill in the elements with holes. 204162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FillFixedArrayWithValue(kind, elements, 204262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrOrSmiConstant(0, capacity_mode), capacity, 204362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kTheHoleValueRootIndex, capacity_mode); 204462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return array; 2047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::AllocateFixedArray(ElementsKind kind, 2050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* capacity_node, 2051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ParameterMode mode, 2052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AllocationFlags flags) { 205362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IntPtrOrSmiGreaterThan(capacity_node, 205462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrOrSmiConstant(0, mode), mode)); 2055f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* total_size = GetFixedArrayAllocationSize(capacity_node, kind, mode); 2056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Allocate both array and elements object, and initialize the JSArray. 2058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* array = Allocate(total_size, flags); 205962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::RootListIndex map_index = IsFastDoubleElementsKind(kind) 206062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? Heap::kFixedDoubleArrayMapRootIndex 206162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : Heap::kFixedArrayMapRootIndex; 206262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(map_index)); 206362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(array, map_index); 2064f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(array, FixedArray::kLengthOffset, 206562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterToTagged(capacity_node, mode)); 2066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return array; 2067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2069f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::FillFixedArrayWithValue( 2070f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind kind, Node* array, Node* from_node, Node* to_node, 2071f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Heap::RootListIndex value_root_index, ParameterMode mode) { 2072f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool is_double = IsFastDoubleElementsKind(kind); 2073f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(value_root_index == Heap::kTheHoleValueRootIndex || 2074f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch value_root_index == Heap::kUndefinedValueRootIndex); 2075f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_IMPLIES(is_double, value_root_index == Heap::kTheHoleValueRootIndex); 2076f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(kHoleNanLower32 == kHoleNanUpper32); 2077bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* double_hole = 2078bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32); 2079f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = LoadRoot(value_root_index); 2080f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2081c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BuildFastFixedArrayForEach( 2082c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch array, kind, from_node, to_node, 208362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [this, value, is_double, double_hole](Node* array, Node* offset) { 2084c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (is_double) { 2085c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Don't use doubles to store the hole double, since manipulating the 2086c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // signaling NaN used for the hole in C++, e.g. with bit_cast, will 2087c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // change its value on ia32 (the x87 stack is used to return values 2088c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // and stores to the stack silently clear the signalling bit). 2089c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 2090c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // TODO(danno): When we have a Float32/Float64 wrapper class that 2091c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // preserves double bits during manipulation, remove this code/change 2092c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // this to an indexed Float64 store. 209362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (Is64()) { 209462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord64, array, offset, 209562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch double_hole); 2096c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 209762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, array, offset, 209862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch double_hole); 209962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, array, 210062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrAdd(offset, IntPtrConstant(kPointerSize)), 210162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch double_hole); 2102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 210462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kTagged, array, offset, 210562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value); 2106bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch }, 2108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mode); 2109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2110bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::CopyFixedArrayElements( 2112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind from_kind, Node* from_array, ElementsKind to_kind, 2113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* to_array, Node* element_count, Node* capacity, 2114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch WriteBarrierMode barrier_mode, ParameterMode mode) { 2115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); 2116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag; 2117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("[ CopyFixedArrayElements"); 2118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Typed array elements are not supported. 2120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(!IsFixedTypedArrayElementsKind(from_kind)); 2121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(!IsFixedTypedArrayElementsKind(to_kind)); 2122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label done(this); 2124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool from_double_elements = IsFastDoubleElementsKind(from_kind); 2125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool to_double_elements = IsFastDoubleElementsKind(to_kind); 2126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool element_size_matches = 2127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Is64() || 2128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IsFastDoubleElementsKind(from_kind) == IsFastDoubleElementsKind(to_kind); 2129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool doubles_to_objects_conversion = 2130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IsFastDoubleElementsKind(from_kind) && IsFastObjectElementsKind(to_kind); 2131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool needs_write_barrier = 2132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch doubles_to_objects_conversion || (barrier_mode == UPDATE_WRITE_BARRIER && 2133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IsFastObjectElementsKind(to_kind)); 2134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* double_hole = 2135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32); 2136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (doubles_to_objects_conversion) { 2138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // If the copy might trigger a GC, make sure that the FixedArray is 2139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // pre-initialized with holes to make sure that it's always in a 2140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // consistent state. 2141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FillFixedArrayWithValue(to_kind, to_array, IntPtrOrSmiConstant(0, mode), 2142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch capacity, Heap::kTheHoleValueRootIndex, mode); 2143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if (element_count != capacity) { 2144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FillFixedArrayWithValue(to_kind, to_array, element_count, capacity, 2145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Heap::kTheHoleValueRootIndex, mode); 2146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* limit_offset = ElementOffsetFromIndex( 2149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrOrSmiConstant(0, mode), from_kind, mode, first_element_offset); 215062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_from_offset(this, MachineType::PointerRepresentation(), 215162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ElementOffsetFromIndex(element_count, from_kind, 215262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch mode, first_element_offset)); 2153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This second variable is used only when the element sizes of source and 2154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // destination arrays do not match. 2155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_to_offset(this, MachineType::PointerRepresentation()); 2156f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (element_size_matches) { 2157f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_to_offset.Bind(var_from_offset.value()); 2158f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2159f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_to_offset.Bind(ElementOffsetFromIndex(element_count, to_kind, mode, 2160f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch first_element_offset)); 2161f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2162f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2163f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable* vars[] = {&var_from_offset, &var_to_offset}; 2164f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label decrement(this, 2, vars); 2165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2166f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(WordEqual(var_from_offset.value(), limit_offset), &done, &decrement); 2167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&decrement); 2169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* from_offset = IntPtrSub( 2171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_from_offset.value(), 2172f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrConstant(from_double_elements ? kDoubleSize : kPointerSize)); 2173f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_from_offset.Bind(from_offset); 2174f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2175f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* to_offset; 2176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (element_size_matches) { 2177f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch to_offset = from_offset; 2178f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2179f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch to_offset = IntPtrSub( 2180f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_to_offset.value(), 2181f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrConstant(to_double_elements ? kDoubleSize : kPointerSize)); 2182f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_to_offset.Bind(to_offset); 2183f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2184f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2185f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label next_iter(this), store_double_hole(this); 2186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_hole; 2187f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (doubles_to_objects_conversion) { 2188f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The target elements array is already preinitialized with holes, so we 2189f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // can just proceed with the next iteration. 2190f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_hole = &next_iter; 2191f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if (IsFastDoubleElementsKind(to_kind)) { 2192f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_hole = &store_double_hole; 2193f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2194f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // In all the other cases don't check for holes and copy the data as is. 2195f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_hole = nullptr; 2196f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2197f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2198f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = LoadElementAndPrepareForStore( 2199f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch from_array, var_from_offset.value(), from_kind, to_kind, if_hole); 2200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (needs_write_barrier) { 220262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Store(to_array, to_offset, value); 2203f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if (to_double_elements) { 2204f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreNoWriteBarrier(MachineRepresentation::kFloat64, to_array, to_offset, 2205f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch value); 2206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 2207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kTagged, to_array, to_offset, 2208c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value); 2209f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2210f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&next_iter); 2211f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2212f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (if_hole == &store_double_hole) { 2213f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&store_double_hole); 2214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Don't use doubles to store the hole double, since manipulating the 2215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // signaling NaN used for the hole in C++, e.g. with bit_cast, will 2216f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // change its value on ia32 (the x87 stack is used to return values 2217f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // and stores to the stack silently clear the signalling bit). 2218f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 2219f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(danno): When we have a Float32/Float64 wrapper class that 2220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // preserves double bits during manipulation, remove this code/change 2221f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // this to an indexed Float64 store. 2222f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (Is64()) { 2223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord64, to_array, to_offset, 2224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch double_hole); 2225f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2226f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, to_array, to_offset, 2227f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch double_hole); 2228f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, to_array, 2229f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrAdd(to_offset, IntPtrConstant(kPointerSize)), 2230f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch double_hole); 2231f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2232f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&next_iter); 2233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2234f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2235f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&next_iter); 2236f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* compare = WordNotEqual(from_offset, limit_offset); 2237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(compare, &decrement, &done); 2238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&done); 2241f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); 2242f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("] CopyFixedArrayElements"); 2243f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2244f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 224562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::CopyStringCharacters(Node* from_string, Node* to_string, 224662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* from_index, Node* to_index, 224762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* character_count, 224862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch String::Encoding from_encoding, 224962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch String::Encoding to_encoding, 225062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterMode mode) { 2251c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool from_one_byte = from_encoding == String::ONE_BYTE_ENCODING; 2252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool to_one_byte = to_encoding == String::ONE_BYTE_ENCODING; 2253c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_IMPLIES(to_one_byte, from_one_byte); 2254c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Comment("CopyStringCharacters %s -> %s", 2255c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch from_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING", 2256c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch to_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING"); 2257c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2258c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementsKind from_kind = from_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS; 2259c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementsKind to_kind = to_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS; 2260c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); 2261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int header_size = SeqOneByteString::kHeaderSize - kHeapObjectTag; 2262c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* from_offset = 2263c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementOffsetFromIndex(from_index, from_kind, mode, header_size); 2264c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* to_offset = 2265c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementOffsetFromIndex(to_index, to_kind, mode, header_size); 2266c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* byte_count = ElementOffsetFromIndex(character_count, from_kind, mode); 226762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* limit_offset = IntPtrAdd(from_offset, byte_count); 2268c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2269c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Prepare the fast loop 2270c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineType type = 2271c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch from_one_byte ? MachineType::Uint8() : MachineType::Uint16(); 2272c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineRepresentation rep = to_one_byte ? MachineRepresentation::kWord8 2273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : MachineRepresentation::kWord16; 2274c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int from_increment = 1 << ElementsKindToShiftSize(from_kind); 2275c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int to_increment = 1 << ElementsKindToShiftSize(to_kind); 2276c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 227762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable current_to_offset(this, MachineType::PointerRepresentation(), 227862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch to_offset); 2279c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableList vars({¤t_to_offset}, zone()); 2280c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int to_index_constant = 0, from_index_constant = 0; 2281c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Smi* to_index_smi = nullptr; 2282c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Smi* from_index_smi = nullptr; 2283c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool index_same = (from_encoding == to_encoding) && 2284c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (from_index == to_index || 2285c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (ToInt32Constant(from_index, from_index_constant) && 2286c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ToInt32Constant(to_index, to_index_constant) && 2287c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch from_index_constant == to_index_constant) || 2288c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (ToSmiConstant(from_index, from_index_smi) && 2289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ToSmiConstant(to_index, to_index_smi) && 2290c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch to_index_smi == from_index_smi)); 229162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BuildFastLoop(vars, from_offset, limit_offset, 229262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [this, from_string, to_string, ¤t_to_offset, to_increment, 229362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch type, rep, index_same](Node* offset) { 229462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = Load(type, from_string, offset); 229562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier( 2296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch rep, to_string, 2297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch index_same ? offset : current_to_offset.value(), value); 2298c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!index_same) { 229962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Increment(current_to_offset, to_increment); 2300c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2301c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch }, 230262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch from_increment, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); 2303f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2304f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2305f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array, 2306f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* offset, 2307f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind from_kind, 2308f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind to_kind, 2309f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_hole) { 2310f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsFastDoubleElementsKind(from_kind)) { 2311f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = 2312f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64()); 2313f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (!IsFastDoubleElementsKind(to_kind)) { 2314f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch value = AllocateHeapNumberWithValue(value); 2315f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2316f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return value; 2317f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2318f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2319c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value = Load(MachineType::AnyTagged(), array, offset); 2320f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (if_hole) { 2321f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(WordEqual(value, TheHoleConstant()), if_hole); 2322f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2323f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsFastDoubleElementsKind(to_kind)) { 2324f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsFastSmiElementsKind(from_kind)) { 2325f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch value = SmiToFloat64(value); 2326f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2327f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch value = LoadHeapNumberValue(value); 2328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2329f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2330f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return value; 2331f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::CalculateNewElementsCapacity(Node* old_capacity, 2335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ParameterMode mode) { 233662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* half_old_capacity = WordOrSmiShr(old_capacity, 1, mode); 233762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_capacity = IntPtrOrSmiAdd(half_old_capacity, old_capacity, mode); 233862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* padding = IntPtrOrSmiConstant(16, mode); 233962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntPtrOrSmiAdd(new_capacity, padding, mode); 2340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2342f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::TryGrowElementsCapacity(Node* object, Node* elements, 2343f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind kind, Node* key, 2344f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* bailout) { 2345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* capacity = LoadFixedArrayBaseLength(elements); 2346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2347f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ParameterMode mode = OptimalParameterMode(); 234862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch capacity = TaggedToParameter(capacity, mode); 234962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch key = TaggedToParameter(key, mode); 2350f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2351f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return TryGrowElementsCapacity(object, elements, kind, key, capacity, mode, 2352f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bailout); 2353f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2354f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2355f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::TryGrowElementsCapacity(Node* object, Node* elements, 2356f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind kind, Node* key, 2357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* capacity, 2358f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ParameterMode mode, 2359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* bailout) { 2360f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("TryGrowElementsCapacity"); 2361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the gap growth is too big, fall back to the runtime. 2363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* max_gap = IntPtrOrSmiConstant(JSObject::kMaxGap, mode); 236462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* max_capacity = IntPtrOrSmiAdd(capacity, max_gap, mode); 236562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(UintPtrOrSmiGreaterThanOrEqual(key, max_capacity, mode), bailout); 2366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2367f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Calculate the capacity of the new backing store. 2368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* new_capacity = CalculateNewElementsCapacity( 236962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrOrSmiAdd(key, IntPtrOrSmiConstant(1, mode), mode), mode); 2370f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return GrowElementsCapacity(object, elements, kind, kind, capacity, 2371f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch new_capacity, mode, bailout); 2372f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2374f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::GrowElementsCapacity( 2375f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* object, Node* elements, ElementsKind from_kind, ElementsKind to_kind, 2376f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* capacity, Node* new_capacity, ParameterMode mode, Label* bailout) { 2377f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("[ GrowElementsCapacity"); 2378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If size of the allocation for the new capacity doesn't fit in a page 2379f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // that we can bump-pointer allocate from, fall back to the runtime. 2380f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int max_size = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(to_kind); 238162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(UintPtrOrSmiGreaterThanOrEqual( 238262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch new_capacity, IntPtrOrSmiConstant(max_size, mode), mode), 2383f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bailout); 2384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Allocate the new backing store. 2386f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* new_elements = AllocateFixedArray(to_kind, new_capacity, mode); 2387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Copy the elements from the old elements store to the new. 2389f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The size-check above guarantees that the |new_elements| is allocated 2390f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // in new space so we can skip the write barrier. 2391f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CopyFixedArrayElements(from_kind, elements, to_kind, new_elements, capacity, 2392f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch new_capacity, SKIP_WRITE_BARRIER, mode); 2393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2394f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectField(object, JSObject::kElementsOffset, new_elements); 2395f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("] GrowElementsCapacity"); 2396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return new_elements; 2397bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2398bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 239962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::InitializeAllocationMemento(Node* base_allocation, 240062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int base_allocation_size, 240162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* allocation_site) { 2402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreObjectFieldNoWriteBarrier( 2403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch base_allocation, AllocationMemento::kMapOffset + base_allocation_size, 2404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch HeapConstant(Handle<Map>(isolate()->heap()->allocation_memento_map()))); 2405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreObjectFieldNoWriteBarrier( 2406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch base_allocation, 2407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch AllocationMemento::kAllocationSiteOffset + base_allocation_size, 2408bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch allocation_site); 2409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (FLAG_allocation_site_pretenuring) { 2410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* count = LoadObjectField(allocation_site, 2411bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch AllocationSite::kPretenureCreateCountOffset); 2412c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* incremented_count = SmiAdd(count, SmiConstant(Smi::FromInt(1))); 2413bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreObjectFieldNoWriteBarrier(allocation_site, 2414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch AllocationSite::kPretenureCreateCountOffset, 2415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch incremented_count); 2416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2419c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::TryTaggedToFloat64(Node* value, 2420c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* if_valueisnotnumber) { 2421c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label out(this); 2422c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_result(this, MachineRepresentation::kFloat64); 2423c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2424c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {value} is a Smi or a HeapObject. 2425c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_valueissmi(this), if_valueisnotsmi(this); 2426c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); 2427c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2428c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_valueissmi); 2429c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 2430c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the Smi {value}. 2431c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(SmiToFloat64(value)); 2432c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&out); 2433c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2434c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2435c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_valueisnotsmi); 2436c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 2437c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {value} is a HeapNumber. 2438c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_valueisheapnumber(this); 2439c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsHeapNumberMap(LoadMap(value)), &if_valueisheapnumber, 2440c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_valueisnotnumber); 2441c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2442c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_valueisheapnumber); 2443c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 2444c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the floating point value. 2445c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(LoadHeapNumberValue(value)); 2446c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&out); 2447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2448c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2449c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&out); 2450c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_result.value(); 2451c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2452c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { 2454bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // We might need to loop once due to ToNumber conversion. 2455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable var_value(this, MachineRepresentation::kTagged), 2456bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result(this, MachineRepresentation::kFloat64); 2457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label loop(this, &var_value), done_loop(this, &var_result); 2458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_value.Bind(value); 2459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 2460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&loop); 2461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2462c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_valueisnotnumber(this, Label::kDeferred); 2463c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the current {value}. 2465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch value = var_value.value(); 2466bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {value} to Float64 if it is a number and convert it to a number 2468c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // otherwise. 2469c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const result = TryTaggedToFloat64(value, &if_valueisnotnumber); 2470c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(result); 2471c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done_loop); 2472bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2473c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_valueisnotnumber); 2474bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2475c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {value} to a Number first. 2476c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::NonNumberToNumber(isolate()); 2477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_value.Bind(CallStub(callable, context, value)); 2478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 2479bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2481bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&done_loop); 2482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 2483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2485bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { 2486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // We might need to loop once due to ToNumber conversion. 248762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_value(this, MachineRepresentation::kTagged, value), 2488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result(this, MachineRepresentation::kWord32); 2489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label loop(this, &var_value), done_loop(this, &var_result); 2490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 2491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&loop); 2492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the current {value}. 2494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch value = var_value.value(); 2495bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {value} is a Smi or a HeapObject. 2497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_valueissmi(this), if_valueisnotsmi(this); 2498c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); 2499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueissmi); 2501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Convert the Smi {value}. 2503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(SmiToWord32(value)); 2504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&done_loop); 2505bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2506bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2507bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnotsmi); 2508bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if {value} is a HeapNumber. 2510bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_valueisheapnumber(this), 2511bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_valueisnotheapnumber(this, Label::kDeferred); 251262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(LoadMap(value)), &if_valueisheapnumber, 251362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_valueisnotheapnumber); 2514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2515bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisheapnumber); 2516bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2517bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Truncate the floating point value. 2518bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(TruncateHeapNumberValueToWord32(value)); 2519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&done_loop); 2520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2521bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2522bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnotheapnumber); 2523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2524bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Convert the {value} to a Number first. 2525bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Callable callable = CodeFactory::NonNumberToNumber(isolate()); 2526bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_value.Bind(CallStub(callable, context, value)); 2527bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 2528bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2529bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2530bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2531bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&done_loop); 2532bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 2533bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2535bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::TruncateHeapNumberValueToWord32(Node* object) { 2536bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = LoadHeapNumberValue(object); 2537bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return TruncateFloat64ToWord32(value); 2538bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2539bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) { 2541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value32 = RoundFloat64ToInt32(value); 2542bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value64 = ChangeInt32ToFloat64(value32); 2543bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2544bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this); 2545bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2546bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_valueisequal(this), if_valueisnotequal(this); 2547bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal); 2548bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisequal); 2549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 255062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(value32, Int32Constant(0)), &if_valueisint32); 2551c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Int32LessThan(Float64ExtractHighWord32(value), Int32Constant(0)), 2552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_valueisheapnumber, &if_valueisint32); 2553bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2554bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnotequal); 2555bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_valueisheapnumber); 2556bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2557bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 2558bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisint32); 2559bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (Is64()) { 2561bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* result = SmiTag(ChangeInt32ToInt64(value32)); 2562bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 2563bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_join); 2564bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* pair = Int32AddWithOverflow(value32, value32); 2566bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* overflow = Projection(1, pair); 2567bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_overflow(this, Label::kDeferred), if_notoverflow(this); 2568bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(overflow, &if_overflow, &if_notoverflow); 2569bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_overflow); 2570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_valueisheapnumber); 2571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_notoverflow); 2572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 257362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = BitcastWordToTaggedSigned(Projection(0, pair)); 2574bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 2575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_join); 2576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2577bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2578bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2579bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisheapnumber); 2580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2581bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* result = AllocateHeapNumberWithValue(value); 2582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 2583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_join); 2584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2585bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_join); 2586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 2587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2588bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::ChangeInt32ToTagged(Node* value) { 2590bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (Is64()) { 2591bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return SmiTag(ChangeInt32ToInt64(value)); 2592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 2594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* pair = Int32AddWithOverflow(value, value); 2595bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* overflow = Projection(1, pair); 2596bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_overflow(this, Label::kDeferred), if_notoverflow(this), 2597bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_join(this); 2598bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(overflow, &if_overflow, &if_notoverflow); 2599bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_overflow); 2600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2601bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value64 = ChangeInt32ToFloat64(value); 2602bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* result = AllocateHeapNumberWithValue(value64); 2603bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 2604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_join); 2606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_notoverflow); 2607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 260862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = BitcastWordToTaggedSigned(Projection(0, pair)); 2609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 2610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_join); 2612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_join); 2613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 2614bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2616bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::ChangeUint32ToTagged(Node* value) { 2617bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_overflow(this, Label::kDeferred), if_not_overflow(this), 2618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_join(this); 2619bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 2620bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If {value} > 2^31 - 1, we need to store it in a HeapNumber. 2621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(Uint32LessThan(Int32Constant(Smi::kMaxValue), value), &if_overflow, 2622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_not_overflow); 2623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2624bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_not_overflow); 2625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2626bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (Is64()) { 2627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(SmiTag(ChangeUint32ToUint64(value))); 2628bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2629bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If tagging {value} results in an overflow, we need to use a HeapNumber 2630bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // to represent it. 2631bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* pair = Int32AddWithOverflow(value, value); 2632bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* overflow = Projection(1, pair); 2633bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(overflow, &if_overflow); 2634bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 263562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = BitcastWordToTaggedSigned(Projection(0, pair)); 2636bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 2637bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2638bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2639bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_join); 2640bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2641bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_overflow); 2642bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* float64_value = ChangeUint32ToFloat64(value); 2644bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(AllocateHeapNumberWithValue(float64_value)); 2645bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2646bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_join); 2647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2648bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_join); 2649bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 2650bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2651bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2652bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::ToThisString(Node* context, Node* value, 2653bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch char const* method_name) { 265462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_value(this, MachineRepresentation::kTagged, value); 2655bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2656bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {value} is a Smi or a HeapObject. 2657bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this), 2658bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_valueisstring(this); 2659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); 2660bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnotsmi); 2661bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2662bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the instance type of the {value}. 2663bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value_instance_type = LoadInstanceType(value); 2664bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2665bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {value} is already String. 2666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_valueisnotstring(this, Label::kDeferred); 2667f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(IsStringInstanceType(value_instance_type), &if_valueisstring, 2668f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &if_valueisnotstring); 2669bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnotstring); 2670bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2671bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {value} is null. 2672bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_valueisnullorundefined(this, Label::kDeferred), 2673bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_valueisnotnullorundefined(this, Label::kDeferred), 2674bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_valueisnotnull(this, Label::kDeferred); 2675bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined, 2676bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_valueisnotnull); 2677bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnotnull); 2678bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2679bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {value} is undefined. 2680bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(WordEqual(value, UndefinedConstant()), 2681bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_valueisnullorundefined, &if_valueisnotnullorundefined); 2682bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnotnullorundefined); 2683bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2684bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Convert the {value} to a String. 2685bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Callable callable = CodeFactory::ToString(isolate()); 2686bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_value.Bind(CallStub(callable, context, value)); 2687bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_valueisstring); 2688bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2689bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2691bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisnullorundefined); 2692bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The {value} is either null or undefined. 2694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context, 2695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch HeapConstant(factory()->NewStringFromAsciiChecked( 2696bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch method_name, TENURED))); 269762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unreachable(); 2698bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2699bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2701bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueissmi); 2702bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2703bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The {value} is a Smi, convert it to a String. 2704bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Callable callable = CodeFactory::NumberToString(isolate()); 2705bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_value.Bind(CallStub(callable, context, value)); 2706bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_valueisstring); 2707bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2708bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_valueisstring); 2709bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_value.value(); 2710bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2711bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 271262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::ChangeNumberToFloat64(compiler::Node* value) { 271362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable result(this, MachineRepresentation::kFloat64); 271462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label smi(this); 271562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label done(this, &result); 271662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(value), &smi); 271762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result.Bind( 271862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(value, HeapNumber::kValueOffset, MachineType::Float64())); 271962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done); 272062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 272162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&smi); 272262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 272362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result.Bind(SmiToFloat64(value)); 272462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done); 272562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 272662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 272762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&done); 272862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return result.value(); 272962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 273062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::ToThisValue(Node* context, Node* value, 2732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch PrimitiveType primitive_type, 2733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch char const* method_name) { 2734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We might need to loop once due to JSValue unboxing. 273562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_value(this, MachineRepresentation::kTagged, value); 2736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label loop(this, &var_value), done_loop(this), 2737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch done_throw(this, Label::kDeferred); 2738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 2739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&loop); 2740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the current {value}. 2742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch value = var_value.value(); 2743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if the {value} is a Smi or a HeapObject. 2745c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(value), (primitive_type == PrimitiveType::kNumber) 2746c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ? &done_loop 2747c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : &done_throw); 2748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the mape of the {value}. 2750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value_map = LoadMap(value); 2751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the instance type of the {value}. 2753f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value_instance_type = LoadMapInstanceType(value_map); 2754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {value} is a JSValue. 2756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_valueisvalue(this, Label::kDeferred), if_valueisnotvalue(this); 2757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(Word32Equal(value_instance_type, Int32Constant(JS_VALUE_TYPE)), 2758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &if_valueisvalue, &if_valueisnotvalue); 2759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2760f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_valueisvalue); 2761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the actual value from the {value}. 2763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_value.Bind(LoadObjectField(value, JSValue::kValueOffset)); 2764f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 2765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2767f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_valueisnotvalue); 2768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2769f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (primitive_type) { 2770f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case PrimitiveType::kBoolean: 2771f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf(WordEqual(value_map, BooleanMapConstant()), &done_loop); 2772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 2773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case PrimitiveType::kNumber: 2774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf( 2775f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)), 2776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &done_loop); 2777f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 2778f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case PrimitiveType::kString: 2779f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(IsStringInstanceType(value_instance_type), &done_loop); 2780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 2781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case PrimitiveType::kSymbol: 2782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf(Word32Equal(value_instance_type, Int32Constant(SYMBOL_TYPE)), 2783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &done_loop); 2784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 2785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&done_throw); 2787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2788f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2789f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2790f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&done_throw); 2791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The {value} is not a compatible receiver for this method. 2793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CallRuntime(Runtime::kThrowNotGeneric, context, 2794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HeapConstant(factory()->NewStringFromAsciiChecked(method_name, 2795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TENURED))); 279662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unreachable(); 2797f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2798f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2799f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&done_loop); 2800f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return var_value.value(); 2801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2803f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::ThrowIfNotInstanceType(Node* context, Node* value, 2804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch InstanceType instance_type, 2805f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch char const* method_name) { 2806f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label out(this), throw_exception(this, Label::kDeferred); 2807f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_value_map(this, MachineRepresentation::kTagged); 2808f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2809c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(value), &throw_exception); 2810f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Load the instance type of the {value}. 2812f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_value_map.Bind(LoadMap(value)); 2813f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const value_instance_type = LoadMapInstanceType(var_value_map.value()); 2814f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2815f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(Word32Equal(value_instance_type, Int32Constant(instance_type)), &out, 2816f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &throw_exception); 2817f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2818f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The {value} is not a compatible receiver for this method. 2819f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&throw_exception); 2820f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallRuntime( 2821f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Runtime::kThrowIncompatibleMethodReceiver, context, 2822f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch HeapConstant(factory()->NewStringFromAsciiChecked(method_name, TENURED)), 2823f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch value); 282462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unreachable(); 2825f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2826f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&out); 2827f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_value_map.value(); 2828f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2829f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 283062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::InstanceTypeEqual(Node* instance_type, int type) { 283162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Word32Equal(instance_type, Int32Constant(type)); 283262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 283362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsSpecialReceiverMap(Node* map) { 2835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* is_special = IsSpecialReceiverInstanceType(LoadMapInstanceType(map)); 2836c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch uint32_t mask = 2837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; 2838c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch USE(mask); 2839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Interceptors or access checks imply special receiver. 284062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, 284162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SelectConstant(IsSetWord32(LoadMapBitField(map), mask), is_special, 284262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(1), MachineRepresentation::kWord32)); 2843c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return is_special; 2844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsDictionaryMap(Node* map) { 2847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_SLOW_ASSERT(this, IsMap(map)); 2848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* bit_field3 = LoadMapBitField3(map); 2849c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Word32NotEqual(IsSetWord32<Map::DictionaryMap>(bit_field3), 2850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(0)); 2851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2853c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsCallableMap(Node* map) { 2854c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsMap(map)); 2855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Word32NotEqual( 2856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Word32And(LoadMapBitField(map), Int32Constant(1 << Map::kIsCallable)), 2857c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(0)); 2858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2859c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 286062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsCallable(Node* object) { 286162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsCallableMap(LoadMap(object)); 286262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 286362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 286462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsConstructorMap(Node* map) { 286562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsMap(map)); 286662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Word32NotEqual( 286762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32And(LoadMapBitField(map), Int32Constant(1 << Map::kIsConstructor)), 286862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(0)); 286962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 287062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) { 2872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); 2873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Int32LessThanOrEqual(instance_type, 2874c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)); 2875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2877f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::IsStringInstanceType(Node* instance_type) { 2878f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(INTERNALIZED_STRING_TYPE == FIRST_TYPE); 2879f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE)); 2880f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2881f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2882f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) { 2883f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2884f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return Int32GreaterThanOrEqual(instance_type, 2885f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Constant(FIRST_JS_RECEIVER_TYPE)); 2886f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2887f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2888c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsJSReceiver(Node* object) { 2889c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 2890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return IsJSReceiverInstanceType(LoadInstanceType(object)); 2891c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2892c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 289362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsJSReceiverMap(Node* map) { 289462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 289562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsJSReceiverInstanceType(LoadMapInstanceType(map)); 289662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 289762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2898c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsJSObject(Node* object) { 2899c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 2900c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Int32GreaterThanOrEqual(LoadInstanceType(object), 2901c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(FIRST_JS_RECEIVER_TYPE)); 2902c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2903c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2904c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsJSGlobalProxy(Node* object) { 2905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Word32Equal(LoadInstanceType(object), 2906c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(JS_GLOBAL_PROXY_TYPE)); 2907c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2908c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2909c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsMap(Node* map) { 2910c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return HasInstanceType(map, MAP_TYPE); 2911c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2912c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2913c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsJSValue(Node* map) { 2914c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return HasInstanceType(map, JS_VALUE_TYPE); 2915c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2916c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2917c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsJSArray(Node* object) { 2918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return HasInstanceType(object, JS_ARRAY_TYPE); 2919c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2920c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2921c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsWeakCell(Node* object) { 2922c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return HasInstanceType(object, WEAK_CELL_TYPE); 2923c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2924c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 292562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsBoolean(Node* object) { 292662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsBooleanMap(LoadMap(object)); 292762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 292862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 292962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsHeapNumber(Node* object) { 293062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsHeapNumberMap(LoadMap(object)); 293162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 293262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2933c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsName(Node* object) { 2934c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Int32LessThanOrEqual(LoadInstanceType(object), 2935c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(LAST_NAME_TYPE)); 2936c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2937c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2938c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsString(Node* object) { 2939c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Int32LessThanOrEqual(LoadInstanceType(object), 2940c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(FIRST_NONSTRING_TYPE)); 2941c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2942c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 294362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsSymbol(Node* object) { 294462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsSymbolMap(LoadMap(object)); 294562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 294662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 294762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsPrivateSymbol(Node* object) { 294862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Select( 294962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IsSymbol(object), 295062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [=] { 295162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const flags = 295262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiToWord32(LoadObjectField(object, Symbol::kFlagsOffset)); 295362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const int kPrivateMask = 1 << Symbol::kPrivateBit; 295462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsSetWord32(flags, kPrivateMask); 295562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }, 295662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [=] { return Int32Constant(0); }, MachineRepresentation::kWord32); 295762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 295862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2959c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsNativeContext(Node* object) { 2960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordEqual(LoadMap(object), LoadRoot(Heap::kNativeContextMapRootIndex)); 2961c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2963c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsFixedDoubleArray(Node* object) { 2964c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordEqual(LoadMap(object), FixedDoubleArrayMapConstant()); 2965c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2966c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2967c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsHashTable(Node* object) { 2968c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordEqual(LoadMap(object), LoadRoot(Heap::kHashTableMapRootIndex)); 2969c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2970c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2971c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsDictionary(Node* object) { 297262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Word32Or(IsHashTable(object), IsUnseededNumberDictionary(object)); 2973c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2974c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2975c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IsUnseededNumberDictionary(Node* object) { 2976c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordEqual(LoadMap(object), 2977c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LoadRoot(Heap::kUnseededNumberDictionaryMapRootIndex)); 2978c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2979c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 298062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsJSFunction(Node* object) { 298162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return HasInstanceType(object, JS_FUNCTION_TYPE); 298262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 298362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 298462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index, 298562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterMode parameter_mode) { 2986c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsString(string)); 2987c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Translate the {index} into a Word. 298862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch index = ParameterToWord(index, parameter_mode); 2989c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 299062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We may need to loop in case of cons, thin, or sliced strings. 299162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_index(this, MachineType::PointerRepresentation(), index); 299262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_string(this, MachineRepresentation::kTagged, string); 2993bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable var_result(this, MachineRepresentation::kWord32); 2994bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable* loop_vars[] = {&var_index, &var_string}; 2995bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label done_loop(this, &var_result), loop(this, 2, loop_vars); 2996bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 2997bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&loop); 2998bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 2999bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the current {index}. 3000bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch index = var_index.value(); 3001bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the current {string}. 3003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch string = var_string.value(); 3004bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3005bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the instance type of the {string}. 3006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* string_instance_type = LoadInstanceType(string); 3007bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3008bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {string} is a SeqString. 3009bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_stringissequential(this), if_stringisnotsequential(this); 3010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Word32Equal(Word32And(string_instance_type, 3011bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kStringRepresentationMask)), 3012bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kSeqStringTag)), 3013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_stringissequential, &if_stringisnotsequential); 3014bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3015bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringissequential); 3016bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3017bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {string} is a TwoByteSeqString or a OneByteSeqString. 3018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_stringistwobyte(this), if_stringisonebyte(this); 3019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Word32Equal(Word32And(string_instance_type, 3020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kStringEncodingMask)), 3021bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kTwoByteStringTag)), 3022bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_stringistwobyte, &if_stringisonebyte); 3023bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3024bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringisonebyte); 3025bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind( 3027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Load(MachineType::Uint8(), string, 3028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize - 3029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kHeapObjectTag)))); 3030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&done_loop); 3031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3032bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3033bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringistwobyte); 3034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3035bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind( 3036bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Load(MachineType::Uint16(), string, 3037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrAdd(WordShl(index, IntPtrConstant(1)), 3038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrConstant(SeqTwoByteString::kHeaderSize - 3039bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kHeapObjectTag)))); 3040bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&done_loop); 3041bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3042bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3043bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringisnotsequential); 3045bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3046bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {string} is a ConsString. 3047bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_stringiscons(this), if_stringisnotcons(this); 3048bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Word32Equal(Word32And(string_instance_type, 3049bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kStringRepresentationMask)), 3050bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kConsStringTag)), 3051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_stringiscons, &if_stringisnotcons); 3052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3053bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringiscons); 3054bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3055bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check whether the right hand side is the empty string (i.e. if 3056bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // this is really a flat string in a cons string). If that is not 3057bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // the case we flatten the string first. 3058bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_rhsisempty(this), if_rhsisnotempty(this, Label::kDeferred); 3059bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* rhs = LoadObjectField(string, ConsString::kSecondOffset); 3060bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(WordEqual(rhs, EmptyStringConstant()), &if_rhsisempty, 3061bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_rhsisnotempty); 3062bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3063bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_rhsisempty); 3064bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3065bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just operate on the left hand side of the {string}. 3066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_string.Bind(LoadObjectField(string, ConsString::kFirstOffset)); 3067bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 3068bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3069bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3070bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_rhsisnotempty); 3071bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3072bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Flatten the {string} and lookup in the resulting string. 3073bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_string.Bind(CallRuntime(Runtime::kFlattenString, 3074bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NoContextConstant(), string)); 3075bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 3076bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3077bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3078bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringisnotcons); 3080bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3081bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {string} is an ExternalString. 3082bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_stringisexternal(this), if_stringisnotexternal(this); 3083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Word32Equal(Word32And(string_instance_type, 3084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kStringRepresentationMask)), 3085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kExternalStringTag)), 3086bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_stringisexternal, &if_stringisnotexternal); 3087bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3088bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringisexternal); 3089bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3090bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {string} is a short external string. 3091f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label if_stringisnotshort(this), 3092f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_stringisshort(this, Label::kDeferred); 3093bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Word32Equal(Word32And(string_instance_type, 3094bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kShortExternalStringMask)), 3095bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(0)), 3096f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &if_stringisnotshort, &if_stringisshort); 3097bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3098f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_stringisnotshort); 3099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the actual resource data from the {string}. 3101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* string_resource_data = 3102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadObjectField(string, ExternalString::kResourceDataOffset, 3103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MachineType::Pointer()); 3104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3105bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {string} is a TwoByteExternalString or a 3106bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // OneByteExternalString. 3107bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_stringistwobyte(this), if_stringisonebyte(this); 3108bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Word32Equal(Word32And(string_instance_type, 3109bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kStringEncodingMask)), 3110bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(kTwoByteStringTag)), 3111bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_stringistwobyte, &if_stringisonebyte); 3112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringisonebyte); 3114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind( 3116bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Load(MachineType::Uint8(), string_resource_data, index)); 3117bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&done_loop); 3118bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3119bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3120bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringistwobyte); 3121bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(Load(MachineType::Uint16(), string_resource_data, 3123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch WordShl(index, IntPtrConstant(1)))); 3124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&done_loop); 3125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_stringisshort); 3129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The {string} might be compressed, call the runtime. 3131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(SmiToWord32( 3132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CallRuntime(Runtime::kExternalStringGetChar, 3133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NoContextConstant(), string, SmiTag(index)))); 3134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&done_loop); 3135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_stringisnotexternal); 3139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 314062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_stringissliced(this), if_stringisthin(this); 314162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch( 314262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32Equal(Word32And(string_instance_type, 314362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kStringRepresentationMask)), 314462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kSlicedStringTag)), 314562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_stringissliced, &if_stringisthin); 314662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_stringissliced); 314762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 314862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The {string} is a SlicedString, continue with its parent. 314962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* string_offset = 315062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadAndUntagObjectField(string, SlicedString::kOffsetOffset); 315162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* string_parent = 315262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(string, SlicedString::kParentOffset); 315362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_index.Bind(IntPtrAdd(index, string_offset)); 315462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_string.Bind(string_parent); 315562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&loop); 315662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 315762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_stringisthin); 315862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 315962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The {string} is a ThinString, continue with its actual value. 316062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_string.Bind(LoadObjectField(string, ThinString::kActualOffset)); 316162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&loop); 316262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 3163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3164bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3167bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3168bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&done_loop); 3169bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 3170bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 3171bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::StringFromCharCode(Node* code) { 3173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 3174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the {code} is a one-byte char code. 3176bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_codeisonebyte(this), if_codeistwobyte(this, Label::kDeferred), 3177bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_done(this); 3178bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(Int32LessThanOrEqual(code, Int32Constant(String::kMaxOneByteCharCode)), 3179bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_codeisonebyte, &if_codeistwobyte); 3180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_codeisonebyte); 3181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load the isolate wide single character string cache. 3183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* cache = LoadRoot(Heap::kSingleCharacterStringCacheRootIndex); 318462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* code_index = ChangeUint32ToWord(code); 3185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if we have an entry for the {code} in the single character string 3187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // cache already. 3188bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label if_entryisundefined(this, Label::kDeferred), 3189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if_entryisnotundefined(this); 319062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* entry = LoadFixedArrayElement(cache, code_index); 3191bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(WordEqual(entry, UndefinedConstant()), &if_entryisundefined, 3192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &if_entryisnotundefined); 3193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_entryisundefined); 3195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Allocate a new SeqOneByteString for {code} and store it in the {cache}. 3197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* result = AllocateSeqOneByteString(1); 3198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreNoWriteBarrier( 3199bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MachineRepresentation::kWord8, result, 3200bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), code); 320162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(cache, code_index, result); 3202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 3203bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_done); 3204bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3205bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3206bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_entryisnotundefined); 3207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Return the entry from the {cache}. 3209bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(entry); 3210bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_done); 3211bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3212bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3214bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_codeistwobyte); 3215bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 3216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Allocate a new SeqTwoByteString for {code}. 3217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* result = AllocateSeqTwoByteString(1); 3218bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreNoWriteBarrier( 3219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MachineRepresentation::kWord16, result, 3220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), code); 3221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(result); 3222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&if_done); 3223bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 3224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_done); 3226bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 3227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 3228bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3229f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace { 3230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3231f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// A wrapper around CopyStringCharacters which determines the correct string 3232f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// encoding, allocates a corresponding sequential string, and then copies the 3233f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// given character range using CopyStringCharacters. 3234f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// |from_string| must be a sequential string. |from_index| and 3235f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// |character_count| must be Smis s.t. 3236f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. 3237f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, 3238f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* from, Node* from_instance_type, 3239f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* from_index, Node* character_count) { 3240f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch typedef CodeStubAssembler::Label Label; 3241f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch typedef CodeStubAssembler::Variable Variable; 3242f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3243f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label end(a), two_byte_sequential(a); 3244f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_result(a, MachineRepresentation::kTagged); 3245f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const smi_zero = a->SmiConstant(Smi::kZero); 3247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3248f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 3249f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, 3250f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->Int32Constant(kStringEncodingMask)), 3251f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->Int32Constant(0)), 3252f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &two_byte_sequential); 3253f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3254f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The subject string is a sequential one-byte string. 3255f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3256f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result = 3257f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); 3258c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, 3259c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch String::ONE_BYTE_ENCODING, 3260c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch String::ONE_BYTE_ENCODING, 3261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeStubAssembler::SMI_PARAMETERS); 3262f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(result); 3263f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3264f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->Goto(&end); 3265f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3266f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3267f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The subject string is a sequential two-byte string. 3268f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->Bind(&two_byte_sequential); 3269f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3270f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result = 3271f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); 3272c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, 3273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch String::TWO_BYTE_ENCODING, 3274c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch String::TWO_BYTE_ENCODING, 3275c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeStubAssembler::SMI_PARAMETERS); 3276f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(result); 3277f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->Goto(&end); 3279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3280f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3281f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch a->Bind(&end); 3282f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 3283f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 3284f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3285f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} // namespace 3286f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3287f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, 3288f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* to) { 3289f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label end(this); 3290f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label runtime(this); 3291f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 329262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const int_zero = Int32Constant(0); 3293f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 329462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Int32 variables. 329562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_instance_type(this, MachineRepresentation::kWord32, int_zero); 329662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_representation(this, MachineRepresentation::kWord32, int_zero); 3297f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 329862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_from(this, MachineRepresentation::kTagged, from); // Smi. 329962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_string(this, MachineRepresentation::kTagged, string); // String. 330062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); // String. 3301f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 330262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Make sure first argument is a string. 330362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, TaggedIsNotSmi(string)); 330462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsString(string)); 3305f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3306f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Load the instance type of the {string}. 3307f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const instance_type = LoadInstanceType(string); 3308f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_instance_type.Bind(instance_type); 3309f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3310f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Make sure that both from and to are non-negative smis. 3311f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 331262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(TaggedIsPositiveSmi(from), &runtime); 331362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(TaggedIsPositiveSmi(to), &runtime); 3314f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3315f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const substr_length = SmiSub(to, from); 3316f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* const string_length = LoadStringLength(string); 3317f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3318f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Begin dispatching based on substring length. 3319f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3320f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label original_string_or_invalid_length(this); 3321f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(SmiAboveOrEqual(substr_length, string_length), 3322f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &original_string_or_invalid_length); 3323f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3324f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // A real substring (substr_length < string_length). 3325f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3326f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label single_char(this); 3327f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(SmiEqual(substr_length, SmiConstant(Smi::FromInt(1))), &single_char); 3328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3329f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(jgruber): Add an additional case for substring of length == 0? 3330f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3331f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Deal with different string types: update the index if necessary 3332f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // and put the underlying string into var_string. 3333f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3334f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // If the string is not indirect, it can only be sequential or external. 333562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(kIsIndirectStringMask == 333662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (kSlicedStringTag & kConsStringTag & kThinStringTag)); 3337f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(kIsIndirectStringMask != 0); 3338f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label underlying_unpacked(this); 3339f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal( 3340f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Word32And(instance_type, Int32Constant(kIsIndirectStringMask)), 3341f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Constant(0)), 3342f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &underlying_unpacked); 3343f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 334462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The subject string is a sliced, cons, or thin string. 3345f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 334662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label thin_string(this), thin_or_sliced(this); 334762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_representation.Bind( 334862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32And(instance_type, Int32Constant(kStringRepresentationMask))); 334962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf( 335062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32NotEqual(var_representation.value(), Int32Constant(kConsStringTag)), 335162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &thin_or_sliced); 3352f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3353f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Cons string. Check whether it is flat, then fetch first part. 3354f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Flat cons strings have an empty second part. 3355f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3356f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset), 3357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch EmptyStringConstant()), 3358f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &runtime); 3359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3360f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset); 3361f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_string.Bind(first_string_part); 3362f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_instance_type.Bind(LoadInstanceType(first_string_part)); 336362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_representation.Bind(Word32And( 336462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_instance_type.value(), Int32Constant(kStringRepresentationMask))); 3365f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 336662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The loaded first part might be a thin string. 336762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Word32Equal(Word32And(var_instance_type.value(), 336862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kIsIndirectStringMask)), 336962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(0)), 337062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &underlying_unpacked, &thin_string); 3371f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3372f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 337362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&thin_or_sliced); 3374f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 337562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf( 337662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32Equal(var_representation.value(), Int32Constant(kThinStringTag)), 337762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &thin_string); 337862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Otherwise it's a sliced string. 3379f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Fetch parent and correct start index by offset. 338062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* sliced_offset = 338162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(var_string.value(), SlicedString::kOffsetOffset); 3382f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_from.Bind(SmiAdd(from, sliced_offset)); 3383f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset); 3385f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_string.Bind(slice_parent); 3386f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3387f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* slice_parent_instance_type = LoadInstanceType(slice_parent); 3388f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_instance_type.Bind(slice_parent_instance_type); 3389f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 339062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The loaded parent might be a thin string. 339162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Word32Equal(Word32And(var_instance_type.value(), 339262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kIsIndirectStringMask)), 339362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(0)), 339462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &underlying_unpacked, &thin_string); 339562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 339662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 339762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&thin_string); 339862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 339962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* actual_string = 340062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(var_string.value(), ThinString::kActualOffset); 340162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_string.Bind(actual_string); 340262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_instance_type.Bind(LoadInstanceType(actual_string)); 340362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&underlying_unpacked); 3404f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3405f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3406f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The subject string can only be external or sequential string of either 3407f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // encoding at this point. 3408f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label external_string(this); 3409f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&underlying_unpacked); 3410f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3411f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (FLAG_string_slices) { 3412f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label copy_routine(this); 3413f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3414f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Short slice. Copy instead of slicing. 3415f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(SmiLessThan(substr_length, 3416f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SmiConstant(Smi::FromInt(SlicedString::kMinLength))), 3417f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ©_routine); 3418f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3419f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Allocate new sliced string. 3420f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3421f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label two_byte_slice(this); 3422f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 3423f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 3424f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3425f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Counters* counters = isolate()->counters(); 3426f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IncrementCounter(counters->sub_string_native(), 1); 3427f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3428f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(Word32And(var_instance_type.value(), 3429f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Constant(kStringEncodingMask)), 3430f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Constant(0)), 3431f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &two_byte_slice); 3432f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3433f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(AllocateSlicedOneByteString( 3434f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch substr_length, var_string.value(), var_from.value())); 3435f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3436f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3437f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&two_byte_slice); 3438f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3439f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(AllocateSlicedTwoByteString( 3440f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch substr_length, var_string.value(), var_from.value())); 3441f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3442f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3443f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(©_routine); 3444f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3445f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3446f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The subject string can only be external or sequential string of either 3447f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // encoding at this point. 3448f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(kExternalStringTag != 0); 3449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(kSeqStringTag == 0); 345062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(Word32And(var_instance_type.value(), 345162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kExternalStringTag)), 345262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(0)), 345362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &external_string); 3454f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3455f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(AllocAndCopyStringCharacters( 3456f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch this, context, var_string.value(), var_instance_type.value(), 3457f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_from.value(), substr_length)); 3458f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3459f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Counters* counters = isolate()->counters(); 3460f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IncrementCounter(counters->sub_string_native(), 1); 3461f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3462f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3463f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3464f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3465f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Handle external string. 3466f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&external_string); 3467f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 346862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const fake_sequential_string = TryDerefExternalString( 346962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_string.value(), var_instance_type.value(), &runtime); 3470f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3471f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(AllocAndCopyStringCharacters( 3472f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch this, context, fake_sequential_string, var_instance_type.value(), 3473f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_from.value(), substr_length)); 3474f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3475f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Counters* counters = isolate()->counters(); 3476f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IncrementCounter(counters->sub_string_native(), 1); 3477f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3478f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3479f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3480f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3481f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Substrings of length 1 are generated through CharCodeAt and FromCharCode. 3482f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&single_char); 3483f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3484f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* char_code = StringCharCodeAt(var_string.value(), var_from.value()); 3485f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(StringFromCharCode(char_code)); 3486f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3487f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3488f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3489f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&original_string_or_invalid_length); 3490f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3491f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Longer than original string's length or negative: unsafe arguments. 3492f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(SmiAbove(substr_length, string_length), &runtime); 3493f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3494f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Equal length - check if {from, to} == {0, str.length}. 3495c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(SmiAbove(from, SmiConstant(Smi::kZero)), &runtime); 3496f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3497f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Return the original string (substr_length == string_length). 3498f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3499f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Counters* counters = isolate()->counters(); 3500f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IncrementCounter(counters->sub_string_native(), 1); 3501f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3502f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(string); 3503f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3504f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3505f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3506f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Fall back to a runtime call. 3507f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&runtime); 3508f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3509f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind( 3510f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallRuntime(Runtime::kSubString, context, string, from, to)); 3511f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3512f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3513f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3514f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&end); 3515f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 3516f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 3517f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 351862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace { 351962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 352062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* IsExternalStringInstanceType(CodeStubAssembler* a, 352162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const instance_type) { 352262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); 352362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return a->Word32Equal( 352462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch a->Word32And(instance_type, a->Int32Constant(kStringRepresentationMask)), 352562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch a->Int32Constant(kExternalStringTag)); 352662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 352762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 352862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* IsShortExternalStringInstanceType(CodeStubAssembler* a, 352962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const instance_type) { 353062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); 353162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(kShortExternalStringTag != 0); 353262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return a->Word32NotEqual( 353362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)), 353462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch a->Int32Constant(0)); 353562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 353662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 353762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} // namespace 353862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 353962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::TryDerefExternalString(Node* const string, 354062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const instance_type, 354162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_bailout) { 354262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label out(this); 354362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 354462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch USE(IsExternalStringInstanceType); 354562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type)); 354662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout); 354762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 354862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Move the pointer so that offset-wise, it looks like a sequential string. 354962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 355062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 355162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* resource_data = LoadObjectField( 355262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch string, ExternalString::kResourceDataOffset, MachineType::Pointer()); 355362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const fake_sequential_string = 355462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrSub(resource_data, 355562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 355662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 355762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return fake_sequential_string; 355862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 355962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 356062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string, 356162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* instance_type, 356262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_did_something) { 356362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label deref(this), done(this, var_did_something); 356462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* representation = 356562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32And(instance_type, Int32Constant(kStringRepresentationMask)); 356662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32Equal(representation, Int32Constant(kThinStringTag)), &deref); 356762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32NotEqual(representation, Int32Constant(kConsStringTag)), &done); 356862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Cons string. 356962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* rhs = LoadObjectField(var_string->value(), ConsString::kSecondOffset); 357062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordEqual(rhs, EmptyStringConstant()), &deref); 357162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done); 357262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 357362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&deref); 357462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(ThinString::kActualOffset == ConsString::kFirstOffset); 357562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_string->Bind( 357662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(var_string->value(), ThinString::kActualOffset)); 357762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_did_something->Bind(IntPtrConstant(1)); 357862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done); 357962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 358062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&done); 358162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 358262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 358362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left, 358462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* left_instance_type, 358562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_right, 358662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* right_instance_type, 358762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* did_something) { 358862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_did_something(this, MachineType::PointerRepresentation(), 358962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(0)); 359062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MaybeDerefIndirectString(var_left, left_instance_type, &var_did_something); 359162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MaybeDerefIndirectString(var_right, right_instance_type, &var_did_something); 359262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 359362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordNotEqual(var_did_something.value(), IntPtrConstant(0)), 359462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch did_something); 359562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Fall through if neither string was an indirect string. 359662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 359762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 3598c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, 3599c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocationFlags flags) { 3600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label check_right(this); 3601c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label runtime(this, Label::kDeferred); 3602c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label cons(this); 3603c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 3604c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this, &result); 3605c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done_native(this, &result); 3606c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Counters* counters = isolate()->counters(); 3607c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3608c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* left_length = LoadStringLength(left); 3609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(WordNotEqual(IntPtrConstant(0), left_length), &check_right); 3610c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(right); 3611c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done_native); 3612c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&check_right); 3614c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* right_length = LoadStringLength(right); 3615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons); 3616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(left); 3617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done_native); 3618c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&cons); 362062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 362162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, TaggedIsSmi(left_length)); 362262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, TaggedIsSmi(right_length)); 362362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_length = SmiAdd(left_length, right_length); 362462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(SmiAboveOrEqual(new_length, SmiConstant(String::kMaxLength)), 362562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &runtime); 3626c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 362762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_left(this, MachineRepresentation::kTagged, left); 362862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_right(this, MachineRepresentation::kTagged, right); 362962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* input_vars[2] = {&var_left, &var_right}; 363062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label non_cons(this, 2, input_vars); 363162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label slow(this, Label::kDeferred); 363262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(SmiLessThan(new_length, SmiConstant(ConsString::kMinLength)), 363362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &non_cons); 3634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 363562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result.Bind(NewConsString(context, new_length, var_left.value(), 363662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_right.value(), flags)); 363762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done_native); 3638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 363962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&non_cons); 3640c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 364162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("Full string concatenate"); 364262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* left_instance_type = LoadInstanceType(var_left.value()); 364362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* right_instance_type = LoadInstanceType(var_right.value()); 364462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Compute intersection and difference of instance types. 364562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 364662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* ored_instance_types = 364762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32Or(left_instance_type, right_instance_type); 364862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* xored_instance_types = 364962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32Xor(left_instance_type, right_instance_type); 365062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 365162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if both strings have the same encoding and both are sequential. 365262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32NotEqual(Word32And(xored_instance_types, 365362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kStringEncodingMask)), 365462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(0)), 365562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &runtime); 365662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32NotEqual(Word32And(ored_instance_types, 365762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kStringRepresentationMask)), 365862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(0)), 365962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &slow); 366062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 366162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label two_byte(this); 366262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32Equal(Word32And(ored_instance_types, 366362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kStringEncodingMask)), 366462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(kTwoByteStringTag)), 366562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &two_byte); 366662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // One-byte sequential string case 366762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_string = 366862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS); 366962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CopyStringCharacters(var_left.value(), new_string, SmiConstant(Smi::kZero), 3670c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiConstant(Smi::kZero), left_length, 367162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING, 3672c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SMI_PARAMETERS); 367362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CopyStringCharacters(var_right.value(), new_string, SmiConstant(Smi::kZero), 367462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch left_length, right_length, String::ONE_BYTE_ENCODING, 367562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch String::ONE_BYTE_ENCODING, SMI_PARAMETERS); 3676c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(new_string); 3677c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done_native); 3678c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 367962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&two_byte); 368062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 368162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Two-byte sequential string case 368262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch new_string = 368362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS); 368462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CopyStringCharacters(var_left.value(), new_string, 368562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiConstant(Smi::kZero), SmiConstant(Smi::kZero), 368662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch left_length, String::TWO_BYTE_ENCODING, 368762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch String::TWO_BYTE_ENCODING, SMI_PARAMETERS); 368862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CopyStringCharacters(var_right.value(), new_string, 368962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiConstant(Smi::kZero), left_length, right_length, 369062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING, 369162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SMI_PARAMETERS); 369262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result.Bind(new_string); 369362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done_native); 369462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 369562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 369662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&slow); 369762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 369862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Try to unwrap indirect strings, restart the above attempt on success. 369962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MaybeDerefIndirectStrings(&var_left, left_instance_type, &var_right, 370062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch right_instance_type, &non_cons); 370162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&runtime); 370262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 370362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 3704c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&runtime); 3705c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 3706c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right)); 3707c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 3708c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 3709c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3710c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done_native); 3711c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 3712c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IncrementCounter(counters->string_add_native(), 1); 3713c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 3714c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 3715c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3716c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 3717c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 3718c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 3719c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 372062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::StringFromCodePoint(Node* codepoint, 3721f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch UnicodeEncoding encoding) { 372262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_result(this, MachineRepresentation::kTagged, 372362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch EmptyStringConstant()); 3724f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3725f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label if_isword16(this), if_isword32(this), return_result(this); 3726f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3727f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(Uint32LessThan(codepoint, Int32Constant(0x10000)), &if_isword16, 3728f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &if_isword32); 3729f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3730f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_isword16); 3731f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3732f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(StringFromCharCode(codepoint)); 3733f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&return_result); 3734f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3735f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3736f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_isword32); 3737f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3738f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch switch (encoding) { 3739f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UnicodeEncoding::UTF16: 3740f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 3741f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UnicodeEncoding::UTF32: { 3742f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Convert UTF32 to UTF16 code units, and store as a 32 bit word. 3743f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* lead_offset = Int32Constant(0xD800 - (0x10000 >> 10)); 3744f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3745f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // lead = (codepoint >> 10) + LEAD_OFFSET 3746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* lead = 3747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Add(WordShr(codepoint, Int32Constant(10)), lead_offset); 3748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // trail = (codepoint & 0x3FF) + 0xDC00; 3750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* trail = Int32Add(Word32And(codepoint, Int32Constant(0x3FF)), 3751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Constant(0xDC00)); 3752f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3753f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // codpoint = (trail << 16) | lead; 3754f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch codepoint = Word32Or(WordShl(trail, Int32Constant(16)), lead); 3755f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 3756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3757f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3758f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3759f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = AllocateSeqTwoByteString(2); 3760f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreNoWriteBarrier( 3761f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineRepresentation::kWord32, value, 3762f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), 3763f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch codepoint); 3764f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(value); 3765f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&return_result); 3766f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3767f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3768f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&return_result); 3769f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 3770f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 3771f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3772f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::StringToNumber(Node* context, Node* input) { 3773f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label runtime(this, Label::kDeferred); 3774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label end(this); 3775f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3776f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 3777f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3778f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if string has a cached array index. 3779f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* hash = LoadNameHashField(input); 3780f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* bit = 3781f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Word32And(hash, Int32Constant(String::kContainsCachedArrayIndexMask)); 3782f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32NotEqual(bit, Int32Constant(0)), &runtime); 3783f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind( 3785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash))); 3786f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3787f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3788f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&runtime); 3789f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3790f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(CallRuntime(Runtime::kStringToNumber, context, input)); 3791f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3792f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3793f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3794f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&end); 3795f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 3796f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 3797f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 379862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::NumberToString(Node* context, Node* argument) { 3799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 3800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label runtime(this, Label::kDeferred); 3801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label smi(this); 3802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this, &result); 3803c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3804c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the number string cache. 3805c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* number_string_cache = LoadRoot(Heap::kNumberStringCacheRootIndex); 3806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Make the hash mask from the length of the number string cache. It 3808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // contains two elements (number and string) for each cache entry. 380962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // TODO(ishell): cleanup mask handling. 381062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* mask = 381162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BitcastTaggedToWord(LoadFixedArrayBaseLength(number_string_cache)); 3812c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* one = IntPtrConstant(1); 3813c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mask = IntPtrSub(mask, one); 3814c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(argument), &smi); 3816c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3817c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Argument isn't smi, check to see if it's a heap-number. 3818c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* map = LoadMap(argument); 381962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsHeapNumberMap(map), &runtime); 3820c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3821c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Make a hash from the two 32-bit values of the double. 3822c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* low = 3823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LoadObjectField(argument, HeapNumber::kValueOffset, MachineType::Int32()); 3824c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* high = LoadObjectField(argument, HeapNumber::kValueOffset + kIntSize, 3825c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineType::Int32()); 3826c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* hash = Word32Xor(low, high); 382762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch hash = ChangeInt32ToIntPtr(hash); 3828c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch hash = WordShl(hash, one); 382962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index = WordAnd(hash, SmiUntag(BitcastWordToTagged(mask))); 3830c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3831c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Cache entry's key must be a heap number 383262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number_key = LoadFixedArrayElement(number_string_cache, index); 3833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(number_key), &runtime); 3834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch map = LoadMap(number_key); 383562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsHeapNumberMap(map), &runtime); 3836c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Cache entry's key must match the heap number value we're looking for. 3838c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* low_compare = LoadObjectField(number_key, HeapNumber::kValueOffset, 3839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineType::Int32()); 3840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* high_compare = LoadObjectField( 3841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch number_key, HeapNumber::kValueOffset + kIntSize, MachineType::Int32()); 384262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(low, low_compare), &runtime); 384362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(high, high_compare), &runtime); 3844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 384562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Heap number match, return value from cache entry. 3846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IncrementCounter(isolate()->counters()->number_to_string_native(), 1); 384762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result.Bind(LoadFixedArrayElement(number_string_cache, index, kPointerSize)); 3848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 3849c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&runtime); 3851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 3852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // No cache entry, go to the runtime. 3853c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(CallRuntime(Runtime::kNumberToString, context, argument)); 3854c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 3855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 3856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3857c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&smi); 3858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 3859c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the smi key, make sure it matches the smi we're looking for. 386062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* smi_index = BitcastWordToTagged( 386162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch WordAnd(WordShl(BitcastTaggedToWord(argument), one), mask)); 3862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* smi_key = LoadFixedArrayElement(number_string_cache, smi_index, 0, 3863c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SMI_PARAMETERS); 3864c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(WordNotEqual(smi_key, argument), &runtime); 3865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3866c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Smi match, return value from cache entry. 3867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IncrementCounter(isolate()->counters()->number_to_string_native(), 1); 3868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(LoadFixedArrayElement(number_string_cache, smi_index, 3869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kPointerSize, SMI_PARAMETERS)); 3870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 3871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 3872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 3874c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 3875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 3876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 3877f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::ToName(Node* context, Node* value) { 3878f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label end(this); 3879f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 3880f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3881f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label is_number(this); 3882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(value), &is_number); 3883f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3884f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label not_name(this); 3885f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value_instance_type = LoadInstanceType(value); 3886f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); 3887f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Int32GreaterThan(value_instance_type, Int32Constant(LAST_NAME_TYPE)), 3888f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ¬_name); 3889f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3890f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(value); 3891f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3892f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3893f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&is_number); 3894f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3895f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Callable callable = CodeFactory::NumberToString(isolate()); 3896f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(CallStub(callable, context, value)); 3897f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3898f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3899f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3900f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(¬_name); 3901f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3902f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)), 3903f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &is_number); 3904f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3905f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label not_oddball(this); 3906f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32NotEqual(value_instance_type, Int32Constant(ODDBALL_TYPE)), 3907f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ¬_oddball); 3908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3909f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(LoadObjectField(value, Oddball::kToStringOffset)); 3910f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3911f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3912f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(¬_oddball); 3913f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3914f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(CallRuntime(Runtime::kToName, context, value)); 3915f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3916f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3917f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3918f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3919f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&end); 3920f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 3921f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 3922f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3923f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { 3924f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Assert input is a HeapObject (not smi or heap number) 3925c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(input))); 392662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, Word32BinaryNot(IsHeapNumberMap(LoadMap(input)))); 3927f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3928f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We might need to loop once here due to ToPrimitive conversions. 392962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_input(this, MachineRepresentation::kTagged, input); 3930f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 3931f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label loop(this, &var_input); 3932f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label end(this); 3933f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&loop); 3934f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&loop); 3935f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3936f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Load the current {input} value (known to be a HeapObject). 3937f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* input = var_input.value(); 3938f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3939f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Dispatch on the {input} instance type. 3940f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* input_instance_type = LoadInstanceType(input); 3941f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label if_inputisstring(this), if_inputisoddball(this), 3942f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_inputisreceiver(this, Label::kDeferred), 3943f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_inputisother(this, Label::kDeferred); 3944f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(IsStringInstanceType(input_instance_type), &if_inputisstring); 3945f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(input_instance_type, Int32Constant(ODDBALL_TYPE)), 3946f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &if_inputisoddball); 3947f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver, 3948f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &if_inputisother); 3949f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3950f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_inputisstring); 3951f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3952f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The {input} is a String, use the fast stub to convert it to a Number. 3953f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(StringToNumber(context, input)); 3954f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3955f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3956f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3957f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_inputisoddball); 3958f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3959f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The {input} is an Oddball, we just need to load the Number value of it. 3960f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(LoadObjectField(input, Oddball::kToNumberOffset)); 3961f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3963f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3964f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_inputisreceiver); 3965f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The {input} is a JSReceiver, we need to convert it to a Primitive first 3967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // using the ToPrimitive type conversion, preferably yielding a Number. 3968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Callable callable = CodeFactory::NonPrimitiveToPrimitive( 3969f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch isolate(), ToPrimitiveHint::kNumber); 3970f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result = CallStub(callable, context, input); 3971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3972f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if the {result} is already a Number. 3973f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label if_resultisnumber(this), if_resultisnotnumber(this); 3974c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(result), &if_resultisnumber); 3975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result_map = LoadMap(result); 397662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(result_map), &if_resultisnumber, 3977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &if_resultisnotnumber); 3978f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_resultisnumber); 3980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3981f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The ToPrimitive conversion already gave us a Number, so we're done. 3982f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(result); 3983f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 3984f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3985f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3986f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_resultisnotnumber); 3987f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 3988f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We now have a Primitive {result}, but it's not yet a Number. 3989f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_input.Bind(result); 3990f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&loop); 3991f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3992f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 3993f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3994f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_inputisother); 3995f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 399662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The {input} is something else (e.g. Symbol), let the runtime figure 399762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // out the correct exception. 3998f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Note: We cannot tail call to the runtime here, as js-to-wasm 3999f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // trampolines also use this code currently, and they declare all 4000f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // outgoing parameters as untagged, while we would push a tagged 4001f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // object here. 4002f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(CallRuntime(Runtime::kToNumber, context, input)); 4003f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 4004f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4005f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4006f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4007f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&end); 4008f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 4009f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 4010f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4011f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::ToNumber(Node* context, Node* input) { 4012f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 4013f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label end(this); 4014f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label not_smi(this, Label::kDeferred); 401662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(TaggedIsSmi(input), ¬_smi); 4017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(input); 4018f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 4019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4020f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(¬_smi); 4021f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 4022f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label not_heap_number(this, Label::kDeferred); 4023f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* input_map = LoadMap(input); 402462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsHeapNumberMap(input_map), ¬_heap_number); 4025f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4026f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(input); 4027f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 4028f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4029f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(¬_heap_number); 4030f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 4031f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(NonNumberToNumber(context, input)); 4032f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 4033f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4034f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&end); 4037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 4038f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 4039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 404062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::ToUint32(Node* context, Node* input) { 404162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const float_zero = Float64Constant(0.0); 404262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const float_two_32 = Float64Constant(static_cast<double>(1ULL << 32)); 404362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 404462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label out(this); 404562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 404662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_result(this, MachineRepresentation::kTagged, input); 404762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 404862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Early exit for positive smis. 404962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 405062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // TODO(jgruber): This branch and the recheck below can be removed once we 405162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // have a ToNumber with multiple exits. 405262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this, Label::kDeferred); 405362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(TaggedIsPositiveSmi(input), &out, &next); 405462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 405562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 405662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 405762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const number = ToNumber(context, input); 405862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(number); 405962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 406062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perhaps we have a positive smi now. 406162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 406262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this, Label::kDeferred); 406362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(TaggedIsPositiveSmi(number), &out, &next); 406462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 406562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 406662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 406762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_isnegativesmi(this), if_isheapnumber(this); 406862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(TaggedIsSmi(number), &if_isnegativesmi, &if_isheapnumber); 406962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 407062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_isnegativesmi); 407162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 407262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // floor({input}) mod 2^32 === {input} + 2^32. 407362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const float_number = SmiToFloat64(number); 407462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const float_result = Float64Add(float_number, float_two_32); 407562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const result = ChangeFloat64ToTagged(float_result); 407662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(result); 407762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&out); 407862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 407962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 408062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_isheapnumber); 408162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 408262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label return_zero(this); 408362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const value = LoadHeapNumberValue(number); 408462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 408562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 408662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // +-0. 408762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this); 408862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Float64Equal(value, float_zero), &return_zero, &next); 408962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 409062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 409162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 409262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 409362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NaN. 409462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this); 409562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Float64Equal(value, value), &next, &return_zero); 409662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 409762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 409862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 409962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 410062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // +Infinity. 410162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this); 410262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const positive_infinity = 410362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Float64Constant(std::numeric_limits<double>::infinity()); 410462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Float64Equal(value, positive_infinity), &return_zero, &next); 410562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 410662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 410762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 410862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 410962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -Infinity. 411062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this); 411162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const negative_infinity = 411262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Float64Constant(-1.0 * std::numeric_limits<double>::infinity()); 411362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Float64Equal(value, negative_infinity), &return_zero, &next); 411462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 411562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 411662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 411762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Return floor({input}) mod 2^32 (assuming mod semantics that always return 411862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // positive results). 411962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 412062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* x = Float64Floor(value); 412162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch x = Float64Mod(x, float_two_32); 412262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch x = Float64Add(x, float_two_32); 412362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch x = Float64Mod(x, float_two_32); 412462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 412562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const result = ChangeFloat64ToTagged(x); 412662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(result); 412762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&out); 412862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 412962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 413062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&return_zero); 413162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 413262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(SmiConstant(Smi::kZero)); 413362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&out); 413462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 413562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 413662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 413762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&out); 413862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return var_result.value(); 413962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 414062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 4141c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::ToString(Node* context, Node* input) { 4142c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label is_number(this); 4143c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label runtime(this, Label::kDeferred); 4144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 4145c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this, &result); 4146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(input), &is_number); 4148c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4149c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* input_map = LoadMap(input); 4150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* input_instance_type = LoadMapInstanceType(input_map); 4151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4152c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(input); 4153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(IsStringInstanceType(input_instance_type), &done); 4154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4155c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label not_heap_number(this); 415662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(input_map), &is_number, ¬_heap_number); 4157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&is_number); 4159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(NumberToString(context, input)); 4160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 4161c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4162c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(¬_heap_number); 4163c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 4164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Word32NotEqual(input_instance_type, Int32Constant(ODDBALL_TYPE)), 4165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &runtime); 4166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(LoadObjectField(input, Oddball::kToStringOffset)); 4167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 4168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 4169c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4170c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&runtime); 4171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 4172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(CallRuntime(Runtime::kToString, context, input)); 4173c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 4174c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 4175c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 4177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 4178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 4179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) { 4181c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this); 4182c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 4183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this, &result); 4184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4185c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfJSReceiver(input, &if_isreceiver, &if_isnotreceiver); 4186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isreceiver); 4188c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 4189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {input} to a primitive first passing Number hint. 4190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate()); 4191c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(CallStub(callable, context, input)); 4192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 4193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 4194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4195c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isnotreceiver); 4196c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 4197c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(input); 4198c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 4199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 4200c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 4202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 4203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 4204c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4205f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::ToInteger(Node* context, Node* input, 4206f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ToIntegerTruncationMode mode) { 4207f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We might need to loop once for ToNumber conversion. 420862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_arg(this, MachineRepresentation::kTagged, input); 4209f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label loop(this, &var_arg), out(this); 4210f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&loop); 4211f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&loop); 4212f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 4213f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Shared entry points. 4214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label return_zero(this, Label::kDeferred); 4215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4216f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Load the current {arg} value. 4217f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* arg = var_arg.value(); 4218f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4219f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if {arg} is a Smi. 4220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(arg), &out); 4221f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4222f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if {arg} is a HeapNumber. 4223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label if_argisheapnumber(this), 4224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_argisnotheapnumber(this, Label::kDeferred); 422562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(LoadMap(arg)), &if_argisheapnumber, 422662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_argisnotheapnumber); 4227f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4228f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_argisheapnumber); 4229f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 4230f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Load the floating-point value of {arg}. 4231f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* arg_value = LoadHeapNumberValue(arg); 4232f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4233f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if {arg} is NaN. 423462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64Equal(arg_value, arg_value), &return_zero); 4235f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4236f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Truncate {arg} towards zero. 4237f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = Float64Trunc(arg_value); 4238f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4239f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (mode == kTruncateMinusZero) { 4240f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Truncate -0.0 to 0. 4241f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Float64Equal(value, Float64Constant(0.0)), &return_zero); 4242f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4243f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4244f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_arg.Bind(ChangeFloat64ToTagged(value)); 4245f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&out); 4246f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4247f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4248f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_argisnotheapnumber); 4249f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 4250f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Need to convert {arg} to a Number first. 4251f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Callable callable = CodeFactory::NonNumberToNumber(isolate()); 4252f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_arg.Bind(CallStub(callable, context, arg)); 4253f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&loop); 4254f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4255f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4256f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&return_zero); 4257c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_arg.Bind(SmiConstant(Smi::kZero)); 4258f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&out); 4259f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 4260f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4261f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&out); 4262f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_arg.value(); 4263f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 4264f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4265c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::DecodeWord32(Node* word32, uint32_t shift, 4266c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch uint32_t mask) { 4267f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return Word32Shr(Word32And(word32, Int32Constant(mask)), 4268f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static_cast<int>(shift)); 4269f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 4270f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 4271c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::DecodeWord(Node* word, uint32_t shift, uint32_t mask) { 4272c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift)); 4273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 4274c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4275f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::SetCounter(StatsCounter* counter, int value) { 4276f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (FLAG_native_code_counters && counter->Enabled()) { 4277f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* counter_address = ExternalConstant(ExternalReference(counter)); 427813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, 427913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Int32Constant(value)); 428013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 428113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 428213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 428313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CodeStubAssembler::IncrementCounter(StatsCounter* counter, int delta) { 428413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(delta > 0); 428513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (FLAG_native_code_counters && counter->Enabled()) { 428613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* counter_address = ExternalConstant(ExternalReference(counter)); 428713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = Load(MachineType::Int32(), counter_address); 428813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch value = Int32Add(value, Int32Constant(delta)); 428913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value); 429013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 429113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 429213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 429313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CodeStubAssembler::DecrementCounter(StatsCounter* counter, int delta) { 429413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(delta > 0); 429513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (FLAG_native_code_counters && counter->Enabled()) { 429613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* counter_address = ExternalConstant(ExternalReference(counter)); 429713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = Load(MachineType::Int32(), counter_address); 429813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch value = Int32Sub(value, Int32Constant(delta)); 429913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value); 430013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 430113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 430213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 430362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::Increment(Variable& variable, int value, 430462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterMode mode) { 430562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_IMPLIES(mode == INTPTR_PARAMETERS, 430662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch variable.rep() == MachineType::PointerRepresentation()); 430762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_IMPLIES(mode == SMI_PARAMETERS, 430862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch variable.rep() == MachineRepresentation::kTagged || 430962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch variable.rep() == MachineRepresentation::kTaggedSigned); 431062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch variable.Bind( 431162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrOrSmiAdd(variable.value(), IntPtrOrSmiConstant(value, mode), mode)); 431262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 431362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 4314f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CodeStubAssembler::Use(Label* label) { 4315f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); 4316f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 4317f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 4318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, 4319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable* var_index, Label* if_keyisunique, 432062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_unique, Label* if_bailout) { 4321f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep()); 432262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(MachineRepresentation::kTagged, var_unique->rep()); 432313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("TryToName"); 4324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 432562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_hascachedindex(this), if_keyisnotindex(this), if_thinstring(this); 4326f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Handle Smi and HeapNumber keys. 4327f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); 4328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(if_keyisindex); 4329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 4330f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_keyisnotindex); 433162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* key_map = LoadMap(key); 433262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_unique->Bind(key); 433313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Symbols are unique. 433462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsSymbolMap(key_map), if_keyisunique); 433562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* key_instance_type = LoadMapInstanceType(key_map); 4336f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Miss if |key| is not a String. 4337f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); 433862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsStringInstanceType(key_instance_type), if_bailout); 4339f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // |key| is a String. Check if it has a cached array index. 434013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* hash = LoadNameHashField(key); 4341f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* contains_index = 4342f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask)); 4343f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex); 4344f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // No cached array index. If the string knows that it contains an index, 4345f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // then it must be an uncacheable index. Handle this case in the runtime. 4346f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* not_an_index = 4347f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); 4348f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); 434962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if we have a ThinString. 435062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32Equal(key_instance_type, Int32Constant(THIN_STRING_TYPE)), 435162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_thinstring); 435262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf( 435362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32Equal(key_instance_type, Int32Constant(THIN_ONE_BYTE_STRING_TYPE)), 435462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_thinstring); 4355f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Finally, check if |key| is internalized. 4356f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(kNotInternalizedTag != 0); 4357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* not_internalized = 4358f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); 4359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); 4360f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(if_keyisunique); 4361f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 436262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_thinstring); 436362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_unique->Bind(LoadObjectField(key, ThinString::kActualOffset)); 436462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(if_keyisunique); 436562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 4366f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_hascachedindex); 4367c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash)); 436813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(if_keyisindex); 436913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 437013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 437113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename Dictionary> 437213e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { 4373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize)); 4374f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex + 4375f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch field_index)); 437613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 437713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 4378c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochtemplate Node* CodeStubAssembler::EntryToIndex<NameDictionary>(Node*, int); 4379c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochtemplate Node* CodeStubAssembler::EntryToIndex<GlobalDictionary>(Node*, int); 438062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate Node* CodeStubAssembler::EntryToIndex<SeededNumberDictionary>(Node*, 438162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int); 4382c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4383c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::HashTableComputeCapacity(Node* at_least_space_for) { 4384c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* capacity = IntPtrRoundUpToPowerOfTwo32( 4385c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch WordShl(at_least_space_for, IntPtrConstant(1))); 4386c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return IntPtrMax(capacity, IntPtrConstant(HashTableBase::kMinCapacity)); 4387c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 4388c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 4389c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::IntPtrMax(Node* left, Node* right) { 439062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectConstant(IntPtrGreaterThanOrEqual(left, right), left, right, 439162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 439262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 439362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 439462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IntPtrMin(Node* left, Node* right) { 439562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return SelectConstant(IntPtrLessThanOrEqual(left, right), left, right, 439662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 439762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 439862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 439962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 440062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::GetNumberOfElements(Node* dictionary) { 440162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex); 440262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 440362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 440462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 440562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::SetNumberOfElements(Node* dictionary, 440662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* num_elements_smi) { 440762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex, 440862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch num_elements_smi, SKIP_WRITE_BARRIER); 440962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 441062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 441162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 441262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::GetNumberOfDeletedElements(Node* dictionary) { 441362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadFixedArrayElement(dictionary, 441462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Dictionary::kNumberOfDeletedElementsIndex); 441562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 441662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 441762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 441862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::GetCapacity(Node* dictionary) { 441962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadFixedArrayElement(dictionary, Dictionary::kCapacityIndex); 442062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 442162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 442262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 442362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::GetNextEnumerationIndex(Node* dictionary) { 442462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadFixedArrayElement(dictionary, 442562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Dictionary::kNextEnumerationIndexIndex); 442662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 442762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 442862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 442962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::SetNextEnumerationIndex(Node* dictionary, 443062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* next_enum_index_smi) { 443162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(dictionary, Dictionary::kNextEnumerationIndexIndex, 443262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch next_enum_index_smi, SKIP_WRITE_BARRIER); 4433c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 4434c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 443513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename Dictionary> 443613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CodeStubAssembler::NameDictionaryLookup(Node* dictionary, 443713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* unique_name, Label* if_found, 443813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_name_index, 443913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_not_found, 444062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int inlined_probes, 444162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LookupMode mode) { 4442c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsDictionary(dictionary)); 4443f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); 444462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_IMPLIES(mode == kFindInsertionIndex, 444562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inlined_probes == 0 && if_found == nullptr); 444613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("NameDictionaryLookup"); 444713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 444862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary)); 4449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); 4450f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* hash = ChangeUint32ToWord(LoadNameHash(unique_name)); 445113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 445213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // See Dictionary::FirstProbe(). 4453f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* count = IntPtrConstant(0); 4454f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* entry = WordAnd(hash, mask); 445513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 445613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (int i = 0; i < inlined_probes; i++) { 445713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* index = EntryToIndex<Dictionary>(entry); 445813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_name_index->Bind(index); 445913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 446062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* current = LoadFixedArrayElement(dictionary, index); 446113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(WordEqual(current, unique_name), if_found); 446213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 446313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // See Dictionary::NextProbe(). 4464f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch count = IntPtrConstant(i + 1); 4465f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch entry = WordAnd(IntPtrAdd(entry, count), mask); 446613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 446762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode == kFindInsertionIndex) { 446862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Appease the variable merging algorithm for "Goto(&loop)" below. 446962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_name_index->Bind(IntPtrConstant(0)); 447062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 447113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 447213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* undefined = UndefinedConstant(); 447362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* the_hole = mode == kFindExisting ? nullptr : TheHoleConstant(); 447413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 447562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_count(this, MachineType::PointerRepresentation(), count); 447662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_entry(this, MachineType::PointerRepresentation(), entry); 447713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* loop_vars[] = {&var_count, &var_entry, var_name_index}; 447813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label loop(this, 3, loop_vars); 447913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&loop); 448013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&loop); 4481bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 448213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* entry = var_entry.value(); 448313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 448413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* index = EntryToIndex<Dictionary>(entry); 448513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_name_index->Bind(index); 448613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 448762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* current = LoadFixedArrayElement(dictionary, index); 448813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(WordEqual(current, undefined), if_not_found); 448962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode == kFindExisting) { 449062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordEqual(current, unique_name), if_found); 449162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 449262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(kFindInsertionIndex, mode); 449362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordEqual(current, the_hole), if_not_found); 449462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 449513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 449613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // See Dictionary::NextProbe(). 449762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Increment(var_count); 449862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch entry = WordAnd(IntPtrAdd(entry, var_count.value()), mask); 449913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 450013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_entry.Bind(entry); 450113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&loop); 4502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 4503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 4504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 450513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Instantiate template methods to workaround GCC compilation issue. 450613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate void CodeStubAssembler::NameDictionaryLookup<NameDictionary>( 450762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node*, Node*, Label*, Variable*, Label*, int, LookupMode); 450813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>( 450962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node*, Node*, Label*, Variable*, Label*, int, LookupMode); 451013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 451113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) { 451213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // See v8::internal::ComputeIntegerHash() 451362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* hash = TruncateWordToWord32(key); 451413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch hash = Word32Xor(hash, seed); 451513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)), 451613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Word32Shl(hash, Int32Constant(15))); 451713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); 451813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); 451913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); 452013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch hash = Int32Mul(hash, Int32Constant(2057)); 452113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); 452213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return Word32And(hash, Int32Constant(0x3fffffff)); 452313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 452413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 452513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <typename Dictionary> 4526f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, 4527f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* intptr_index, 452813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_found, 452913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_entry, 453013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_not_found) { 4531c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsDictionary(dictionary)); 4532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_EQ(MachineType::PointerRepresentation(), var_entry->rep()); 453313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("NumberDictionaryLookup"); 453413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 453562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary)); 4536f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); 453713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 4538f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* int32_seed; 453913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (Dictionary::ShapeT::UsesSeed) { 4540f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int32_seed = HashSeed(); 454113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 4542f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int32_seed = Int32Constant(kZeroHashSeed); 454313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 4544f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* hash = ChangeUint32ToWord(ComputeIntegerHash(intptr_index, int32_seed)); 4545f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index); 454613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 454713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // See Dictionary::FirstProbe(). 4548f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* count = IntPtrConstant(0); 4549f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* entry = WordAnd(hash, mask); 455013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 455113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* undefined = UndefinedConstant(); 455213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* the_hole = TheHoleConstant(); 455313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 455462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_count(this, MachineType::PointerRepresentation(), count); 455513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* loop_vars[] = {&var_count, var_entry}; 455613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label loop(this, 2, loop_vars); 455713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_entry->Bind(entry); 455813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&loop); 455913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&loop); 4560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 456113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* entry = var_entry->value(); 456213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 456313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* index = EntryToIndex<Dictionary>(entry); 456462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* current = LoadFixedArrayElement(dictionary, index); 456513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(WordEqual(current, undefined), if_not_found); 456613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label next_probe(this); 456713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 456813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_currentissmi(this), if_currentisnotsmi(this); 4569c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(current), &if_currentissmi, &if_currentisnotsmi); 457013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_currentissmi); 457113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 4572f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* current_value = SmiUntag(current); 4573f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(WordEqual(current_value, intptr_index), if_found, &next_probe); 457413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 457513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_currentisnotsmi); 457613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 457713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(WordEqual(current, the_hole), &next_probe); 457813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Current must be the Number. 457913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* current_value = LoadHeapNumberValue(current); 458013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Branch(Float64Equal(current_value, key_as_float64), if_found, 458113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &next_probe); 458213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 458313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 458413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 458513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&next_probe); 458613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // See Dictionary::NextProbe(). 458762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Increment(var_count); 458862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch entry = WordAnd(IntPtrAdd(entry, var_count.value()), mask); 458913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 459013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_entry->Bind(entry); 459113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&loop); 4592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 459313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 459413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 459562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 459662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::FindInsertionEntry(Node* dictionary, Node* key, 459762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_key_index) { 459862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 459962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 460062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 460162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <> 460262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::FindInsertionEntry<NameDictionary>( 460362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* dictionary, Node* key, Variable* var_key_index) { 460462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label done(this); 460562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NameDictionaryLookup<NameDictionary>(dictionary, key, nullptr, var_key_index, 460662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &done, 0, kFindInsertionIndex); 460762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&done); 460862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 460962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 461062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 461162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::InsertEntry(Node* dictionary, Node* key, Node* value, 461262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index, Node* enum_index) { 461362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); // Use specializations instead. 461462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 461562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 461662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <> 461762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::InsertEntry<NameDictionary>(Node* dictionary, 461862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* name, Node* value, 461962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index, 462062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* enum_index) { 462162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Store name and value. 462262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(dictionary, index, name); 462362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreValueByKeyIndex<NameDictionary>(dictionary, index, value); 462462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 462562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Prepare details of the new property. 462662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const int kInitialIndex = 0; 462762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch PropertyDetails d(kData, NONE, kInitialIndex, PropertyCellType::kNoCell); 462862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch enum_index = 462962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiShl(enum_index, PropertyDetails::DictionaryStorageField::kShift); 463062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(kInitialIndex == 0); 463162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_details(this, MachineRepresentation::kTaggedSigned, 463262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiOr(SmiConstant(d.AsSmi()), enum_index)); 463362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 463462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Private names must be marked non-enumerable. 463562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label not_private(this, &var_details); 463662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsSymbolMap(LoadMap(name)), ¬_private); 463762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* flags = SmiToWord32(LoadObjectField(name, Symbol::kFlagsOffset)); 463862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const int kPrivateMask = 1 << Symbol::kPrivateBit; 463962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsSetWord32(flags, kPrivateMask), ¬_private); 464062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* dont_enum = 464162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiShl(SmiConstant(DONT_ENUM), PropertyDetails::AttributesField::kShift); 464262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_details.Bind(SmiOr(var_details.value(), dont_enum)); 464362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(¬_private); 464462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(¬_private); 464562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 464662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Finally, store the details. 464762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreDetailsByKeyIndex<NameDictionary>(dictionary, index, 464862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_details.value()); 464962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 465062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 465162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <> 465262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::InsertEntry<GlobalDictionary>(Node* dictionary, 465362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* key, Node* value, 465462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index, 465562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* enum_index) { 465662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNIMPLEMENTED(); 465762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 465862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 465962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class Dictionary> 466062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::Add(Node* dictionary, Node* key, Node* value, 466162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* bailout) { 466262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* capacity = GetCapacity<Dictionary>(dictionary); 466362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* nof = GetNumberOfElements<Dictionary>(dictionary); 466462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_nof = SmiAdd(nof, SmiConstant(1)); 466562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Require 33% to still be free after adding additional_elements. 466662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Computing "x + (x >> 1)" on a Smi x does not return a valid Smi! 466762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // But that's OK here because it's only used for a comparison. 466862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* required_capacity_pseudo_smi = SmiAdd(new_nof, SmiShr(new_nof, 1)); 466962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(SmiBelow(capacity, required_capacity_pseudo_smi), bailout); 467062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Require rehashing if more than 50% of free elements are deleted elements. 467162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* deleted = GetNumberOfDeletedElements<Dictionary>(dictionary); 467262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, SmiAbove(capacity, new_nof)); 467362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* half_of_free_elements = SmiShr(SmiSub(capacity, new_nof), 1); 467462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(SmiAbove(deleted, half_of_free_elements), bailout); 467562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* enum_index = nullptr; 467662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (Dictionary::kIsEnumerable) { 467762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch enum_index = GetNextEnumerationIndex<Dictionary>(dictionary); 467862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_enum_index = SmiAdd(enum_index, SmiConstant(1)); 467962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* max_enum_index = 468062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SmiConstant(PropertyDetails::DictionaryStorageField::kMax); 468162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(SmiAbove(new_enum_index, max_enum_index), bailout); 468262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 468362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // No more bailouts after this point. 468462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Operations from here on can have side effects. 468562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 468662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SetNextEnumerationIndex<Dictionary>(dictionary, new_enum_index); 468762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 468862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch USE(enum_index); 468962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 469062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SetNumberOfElements<Dictionary>(dictionary, new_nof); 469162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 469262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_key_index(this, MachineType::PointerRepresentation()); 469362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FindInsertionEntry<Dictionary>(dictionary, key, &var_key_index); 469462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch InsertEntry<Dictionary>(dictionary, key, value, var_key_index.value(), 469562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch enum_index); 469662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 469762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 469862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*, 469962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label*); 470062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 4701f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, 4702f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* descriptors, Node* nof, 4703f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_found, 4704f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable* var_name_index, 4705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_not_found) { 470662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("DescriptorLookupLinear"); 4707c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); 470862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* factor = IntPtrConstant(DescriptorArray::kEntrySize); 4709c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor)); 4710c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 471162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BuildFastLoop(last_exclusive, first_inclusive, 471262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [this, descriptors, unique_name, if_found, 471362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_name_index](Node* name_index) { 471462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* candidate_name = 471562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadFixedArrayElement(descriptors, name_index); 471662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_name_index->Bind(name_index); 471762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordEqual(candidate_name, unique_name), if_found); 471862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }, 471962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch -DescriptorArray::kEntrySize, INTPTR_PARAMETERS, 472062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IndexAdvanceMode::kPre); 4721c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(if_not_found); 4722f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 4723f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 472462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::DescriptorArrayNumberOfEntries(Node* descriptors) { 472562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadAndUntagToWord32FixedArrayElement( 472662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex)); 472762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 472862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 472962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace { 473062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 473162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* DescriptorNumberToIndex(CodeStubAssembler* a, Node* descriptor_number) { 473262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* descriptor_size = a->Int32Constant(DescriptorArray::kEntrySize); 473362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index = a->Int32Mul(descriptor_number, descriptor_size); 473462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return a->ChangeInt32ToIntPtr(index); 473562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 473662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 473762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} // namespace 473862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 473962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::DescriptorArrayToKeyIndex(Node* descriptor_number) { 474062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntPtrAdd(IntPtrConstant(DescriptorArray::ToKeyIndex(0)), 474162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DescriptorNumberToIndex(this, descriptor_number)); 474262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 474362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 474462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::DescriptorArrayGetSortedKeyIndex( 474562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* descriptors, Node* descriptor_number) { 474662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize; 474762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* details = LoadAndUntagToWord32FixedArrayElement( 474862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch descriptors, DescriptorNumberToIndex(this, descriptor_number), 474962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch details_offset); 475062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return DecodeWord32<PropertyDetails::DescriptorPointer>(details); 475162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 475262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 475362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::DescriptorArrayGetKey(Node* descriptors, 475462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* descriptor_number) { 475562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize; 475662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadFixedArrayElement(descriptors, 475762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DescriptorNumberToIndex(this, descriptor_number), 475862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch key_offset); 475962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 476062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 476162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::DescriptorLookupBinary(Node* unique_name, 476262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* descriptors, Node* nof, 476362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_found, 476462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_name_index, 476562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_not_found) { 476662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("DescriptorLookupBinary"); 476762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_low(this, MachineRepresentation::kWord32, Int32Constant(0)); 476862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* limit = 476962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Sub(DescriptorArrayNumberOfEntries(descriptors), Int32Constant(1)); 477062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_high(this, MachineRepresentation::kWord32, limit); 477162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* hash = LoadNameHashField(unique_name); 477262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, Word32NotEqual(hash, Int32Constant(0))); 477362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 477462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Assume non-empty array. 477562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, Uint32LessThanOrEqual(var_low.value(), var_high.value())); 477662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 477762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* loop_vars[] = {&var_high, &var_low}; 477862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label binary_loop(this, 2, loop_vars); 477962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&binary_loop); 478062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&binary_loop); 478162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 478262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // mid = low + (high - low) / 2 (to avoid overflow in "(low + high) / 2"). 478362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* mid = 478462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Add(var_low.value(), 478562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word32Shr(Int32Sub(var_high.value(), var_low.value()), 1)); 478662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // mid_name = descriptors->GetSortedKey(mid). 478762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* sorted_key_index = DescriptorArrayGetSortedKeyIndex(descriptors, mid); 478862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* mid_name = DescriptorArrayGetKey(descriptors, sorted_key_index); 478962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 479062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* mid_hash = LoadNameHashField(mid_name); 479162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 479262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label mid_greater(this), mid_less(this), merge(this); 479362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Uint32GreaterThanOrEqual(mid_hash, hash), &mid_greater, &mid_less); 479462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&mid_greater); 479562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 479662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_high.Bind(mid); 479762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&merge); 479862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 479962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&mid_less); 480062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 480162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_low.Bind(Int32Add(mid, Int32Constant(1))); 480262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&merge); 480362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 480462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&merge); 480562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32NotEqual(var_low.value(), var_high.value()), &binary_loop); 480662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 480762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 480862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label scan_loop(this, &var_low); 480962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&scan_loop); 481062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&scan_loop); 481162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 481262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Int32GreaterThan(var_low.value(), limit), if_not_found); 481362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 481462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* sort_index = 481562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DescriptorArrayGetSortedKeyIndex(descriptors, var_low.value()); 481662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* current_name = DescriptorArrayGetKey(descriptors, sort_index); 481762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* current_hash = LoadNameHashField(current_name); 481862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32NotEqual(current_hash, hash), if_not_found); 481962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label next(this); 482062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(WordNotEqual(current_name, unique_name), &next); 482162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Int32GreaterThanOrEqual(sort_index, nof), if_not_found); 482262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_name_index->Bind(DescriptorArrayToKeyIndex(sort_index)); 482362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(if_found); 482462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 482562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&next); 482662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_low.Bind(Int32Add(var_low.value(), Int32Constant(1))); 482762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&scan_loop); 482862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 482962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 483062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 483162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::DescriptorLookup(Node* unique_name, Node* descriptors, 483262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* bitfield3, Label* if_found, 483362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_name_index, 483462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_not_found) { 483562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Comment("DescriptorArrayLookup"); 483662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); 483762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Word32Equal(nof, Int32Constant(0)), if_not_found); 483862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label linear_search(this), binary_search(this); 483962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const int kMaxElementsForLinearSearch = 32; 484062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxElementsForLinearSearch)), 484162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &linear_search, &binary_search); 484262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&linear_search); 484362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 484462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DescriptorLookupLinear(unique_name, descriptors, ChangeInt32ToIntPtr(nof), 484562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_found, var_name_index, if_not_found); 484662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 484762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&binary_search); 484862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 484962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DescriptorLookupBinary(unique_name, descriptors, nof, if_found, 485062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_name_index, if_not_found); 485162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 485262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 485362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 485413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CodeStubAssembler::TryLookupProperty( 485513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* object, Node* map, Node* instance_type, Node* unique_name, 485613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_found_fast, Label* if_found_dict, Label* if_found_global, 485713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, 485813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_bailout) { 485913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); 4860f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); 486113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 486213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_objectisspecial(this); 486313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); 486413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(Int32LessThanOrEqual(instance_type, 486513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), 486613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_objectisspecial); 486713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 4868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch uint32_t mask = 4869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; 4870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask))); 4871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch USE(mask); 4872bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 4873bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* bit_field3 = LoadMapBitField3(map); 487413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_isfastmap(this), if_isslowmap(this); 4875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap, 4876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_isfastmap); 4877bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_isfastmap); 4878bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 487913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* descriptors = LoadMapDescriptors(map); 488013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_meta_storage->Bind(descriptors); 4881bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 488262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DescriptorLookup(unique_name, descriptors, bit_field3, if_found_fast, 488362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_name_index, if_not_found); 4884bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 488513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_isslowmap); 488613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 488713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* dictionary = LoadProperties(object); 488813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_meta_storage->Bind(dictionary); 488913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 489013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, 489113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_name_index, if_not_found); 489213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 489313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_objectisspecial); 489413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 489513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handle global object here and other special objects in runtime. 489662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)), 489762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_bailout); 489813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 489913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handle interceptors and access checks in runtime. 490013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* bit_field = LoadMapBitField(map); 490113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor | 490213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1 << Map::kIsAccessCheckNeeded); 490313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(Word32NotEqual(Word32And(bit_field, mask), Int32Constant(0)), 490413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_bailout); 490513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 490613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* dictionary = LoadProperties(object); 490713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_meta_storage->Bind(dictionary); 490813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 490913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch NameDictionaryLookup<GlobalDictionary>( 491013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch dictionary, unique_name, if_found_global, var_name_index, if_not_found); 491113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 491213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 491313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 491462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::TryHasOwnProperty(Node* object, Node* map, 491562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* instance_type, 491662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* unique_name, Label* if_found, 491762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_not_found, 491813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_bailout) { 491913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("TryHasOwnProperty"); 492013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_meta_storage(this, MachineRepresentation::kTagged); 4921f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_name_index(this, MachineType::PointerRepresentation()); 492213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 492313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_found_global(this); 492413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch TryLookupProperty(object, map, instance_type, unique_name, if_found, if_found, 492513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_found_global, &var_meta_storage, &var_name_index, 492613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_not_found, if_bailout); 492713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_found_global); 492813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 492913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_value(this, MachineRepresentation::kTagged); 493013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_details(this, MachineRepresentation::kWord32); 493113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Check if the property cell is not deleted. 493213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadPropertyFromGlobalDictionary(var_meta_storage.value(), 493313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_name_index.value(), &var_value, 493413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &var_details, if_not_found); 493513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(if_found); 493613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 493713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 493813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 493913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, 494013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* descriptors, 494113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* name_index, 494213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_details, 494313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_value) { 494413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(MachineRepresentation::kWord32, var_details->rep()); 494513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); 494613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("[ LoadPropertyFromFastObject"); 494713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 494862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* details = 494962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index); 495013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_details->Bind(details); 495113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 4952c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* location = DecodeWord32<PropertyDetails::LocationField>(details); 495313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 495413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_in_field(this), if_in_descriptor(this), done(this); 495513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field, 495613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_in_descriptor); 495713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_in_field); 495813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 495913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* field_index = 4960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details); 496113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* representation = 4962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DecodeWord32<PropertyDetails::RepresentationField>(details); 496313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 496413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* inobject_properties = LoadMapInobjectProperties(map); 496513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 496613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_inobject(this), if_backing_store(this); 496713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_double_value(this, MachineRepresentation::kFloat64); 496813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label rebox_double(this, &var_double_value); 4969c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(UintPtrLessThan(field_index, inobject_properties), &if_inobject, 4970c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_backing_store); 497113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_inobject); 497213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 497313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("if_inobject"); 4974f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* field_offset = 4975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrMul(IntPtrSub(LoadMapInstanceSize(map), 4976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrSub(inobject_properties, field_index)), 4977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrConstant(kPointerSize)); 497813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 497913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_double(this), if_tagged(this); 4980c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32NotEqual(representation, 4981c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(Representation::kDouble)), 4982c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_tagged, &if_double); 498313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_tagged); 498413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 498513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_value->Bind(LoadObjectField(object, field_offset)); 498613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&done); 498713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 498813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_double); 498913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 499013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (FLAG_unbox_double_fields) { 499113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_double_value.Bind( 499213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadObjectField(object, field_offset, MachineType::Float64())); 499313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 499413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* mutable_heap_number = LoadObjectField(object, field_offset); 499513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); 499613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 499713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&rebox_double); 499813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 499913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 500013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_backing_store); 500113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 500213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("if_backing_store"); 500313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* properties = LoadProperties(object); 5004f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch field_index = IntPtrSub(field_index, inobject_properties); 500513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = LoadFixedArrayElement(properties, field_index); 500613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 500713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_double(this), if_tagged(this); 5008c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32NotEqual(representation, 5009c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(Representation::kDouble)), 5010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_tagged, &if_double); 501113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_tagged); 501213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 501313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_value->Bind(value); 501413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&done); 501513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 501613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_double); 501713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 501813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_double_value.Bind(LoadHeapNumberValue(value)); 501913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&rebox_double); 502013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 502113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 502213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&rebox_double); 502313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 502413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("rebox_double"); 5025f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* heap_number = AllocateHeapNumberWithValue(var_double_value.value()); 502613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_value->Bind(heap_number); 502713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&done); 502813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 502913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 503013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_in_descriptor); 503113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 503262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_value->Bind( 503362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadValueByKeyIndex<DescriptorArray>(descriptors, name_index)); 503413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&done); 503513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 503613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&done); 503713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 503813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("] LoadPropertyFromFastObject"); 503913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 504013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 504113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CodeStubAssembler::LoadPropertyFromNameDictionary(Node* dictionary, 504213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* name_index, 504313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_details, 504413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_value) { 504513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("LoadPropertyFromNameDictionary"); 5046c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsDictionary(dictionary)); 504713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 504862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_details->Bind( 504962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadDetailsByKeyIndex<NameDictionary>(dictionary, name_index)); 505062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_value->Bind(LoadValueByKeyIndex<NameDictionary>(dictionary, name_index)); 505113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 505213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("] LoadPropertyFromNameDictionary"); 505313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 505413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 505513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary, 505613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* name_index, 505713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_details, 505813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* var_value, 505913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_deleted) { 506013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("[ LoadPropertyFromGlobalDictionary"); 5061c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsDictionary(dictionary)); 506213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 506313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* property_cell = 506462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadValueByKeyIndex<GlobalDictionary>(dictionary, name_index); 506513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 506613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); 506713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(WordEqual(value, TheHoleConstant()), if_deleted); 506813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 506913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_value->Bind(value); 507013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 5071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* details = LoadAndUntagToWord32ObjectField(property_cell, 5072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch PropertyCell::kDetailsOffset); 507313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var_details->Bind(details); 507413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 507513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("] LoadPropertyFromGlobalDictionary"); 507613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 507713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 5078f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// |value| is the property backing store's contents, which is either a value 5079f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// or an accessor pair, as specified by |details|. 5080f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Returns either the original value, or the result of the getter call. 5081f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details, 5082f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* context, Node* receiver, 5083f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_bailout) { 508462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_value(this, MachineRepresentation::kTagged, value); 5085f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label done(this); 5086f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5087c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* kind = DecodeWord32<PropertyDetails::KindField>(details); 5088f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(kind, Int32Constant(kData)), &done); 5089f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5090f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Accessor case. 5091f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 5092f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* accessor_pair = value; 5093f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(Word32Equal(LoadInstanceType(accessor_pair), 5094f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Int32Constant(ACCESSOR_INFO_TYPE)), 5095f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_bailout); 5096c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, HasInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE)); 5097f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); 5098f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* getter_map = LoadMap(getter); 5099f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* instance_type = LoadMapInstanceType(getter_map); 5100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // FunctionTemplateInfo getters are not supported yet. 5101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf( 5102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Word32Equal(instance_type, Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)), 5103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_bailout); 5104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Return undefined if the {getter} is not callable. 5106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_value.Bind(UndefinedConstant()); 510762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsCallableMap(getter_map), &done); 5108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Call the accessor. 5110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Callable callable = CodeFactory::Call(isolate()); 5111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* result = CallJS(callable, context, getter, receiver); 5112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_value.Bind(result); 5113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&done); 5114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&done); 5117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_value.value(); 5118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::TryGetOwnProperty( 5121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* context, Node* receiver, Node* object, Node* map, Node* instance_type, 5122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* unique_name, Label* if_found_value, Variable* var_value, 5123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_not_found, Label* if_bailout) { 512413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); 512513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Comment("TryGetOwnProperty"); 512613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 512713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_meta_storage(this, MachineRepresentation::kTagged); 5128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_entry(this, MachineType::PointerRepresentation()); 512913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 513013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_found_fast(this), if_found_dict(this), if_found_global(this); 513113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 513213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable var_details(this, MachineRepresentation::kWord32); 513313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Variable* vars[] = {var_value, &var_details}; 513413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_found(this, 2, vars); 513513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 513613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch TryLookupProperty(object, map, instance_type, unique_name, &if_found_fast, 513713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_found_dict, &if_found_global, &var_meta_storage, 513813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &var_entry, if_not_found, if_bailout); 513913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_found_fast); 514013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 514113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* descriptors = var_meta_storage.value(); 514213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* name_index = var_entry.value(); 514313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 514413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadPropertyFromFastObject(object, map, descriptors, name_index, 514513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &var_details, var_value); 514613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_found); 514713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 514813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_found_dict); 514913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 515013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* dictionary = var_meta_storage.value(); 515113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* entry = var_entry.value(); 515213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadPropertyFromNameDictionary(dictionary, entry, &var_details, var_value); 515313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_found); 515413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 515513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_found_global); 515613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 515713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* dictionary = var_meta_storage.value(); 515813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* entry = var_entry.value(); 515913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 516013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadPropertyFromGlobalDictionary(dictionary, entry, &var_details, var_value, 516113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_not_found); 516213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_found); 516313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 516413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Here we have details and value which could be an accessor. 516513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_found); 516613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 5167f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = CallGetterIfAccessor(var_value->value(), var_details.value(), 5168f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch context, receiver, if_bailout); 5169f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_value->Bind(value); 5170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(if_found_value); 517113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 5172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 5173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid CodeStubAssembler::TryLookupElement(Node* object, Node* map, 5175f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* instance_type, 5176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* intptr_index, Label* if_found, 5177f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* if_not_found, 517813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* if_bailout) { 517913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handle special objects in runtime. 518013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(Int32LessThanOrEqual(instance_type, 518113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), 518213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_bailout); 5183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5184f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* elements_kind = LoadMapElementsKind(map); 5185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // TODO(verwaest): Support other elements kinds as well. 518713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this), 5188f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this); 518913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // clang-format off 519013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int32_t values[] = { 519113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handled by {if_isobjectorsmi}. 519213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, 519313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FAST_HOLEY_ELEMENTS, 519413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handled by {if_isdouble}. 519513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, 519613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handled by {if_isdictionary}. 519713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DICTIONARY_ELEMENTS, 519813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handled by {if_isfaststringwrapper}. 519913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FAST_STRING_WRAPPER_ELEMENTS, 520013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handled by {if_isslowstringwrapper}. 520113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch SLOW_STRING_WRAPPER_ELEMENTS, 520213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Handled by {if_not_found}. 520313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch NO_ELEMENTS, 520413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch }; 520513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label* labels[] = { 520613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi, 520713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_isobjectorsmi, 520813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_isdouble, &if_isdouble, 520913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_isdictionary, 521013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_isfaststringwrapper, 521113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &if_isslowstringwrapper, 521213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_not_found, 521313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch }; 521413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // clang-format on 521513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch STATIC_ASSERT(arraysize(values) == arraysize(labels)); 521613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Switch(elements_kind, if_bailout, values, labels, arraysize(values)); 521713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 5218bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&if_isobjectorsmi); 5219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 5220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* elements = LoadElements(object); 5221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* length = LoadAndUntagFixedArrayBaseLength(elements); 5222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 522362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(UintPtrLessThan(intptr_index, length), &if_oob); 5224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 522562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* element = LoadFixedArrayElement(elements, intptr_index); 522613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* the_hole = TheHoleConstant(); 5227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Branch(WordEqual(element, the_hole), if_not_found, if_found); 5228bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 522913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_isdouble); 523013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 523113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* elements = LoadElements(object); 5232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* length = LoadAndUntagFixedArrayBaseLength(elements); 523313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 523462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(UintPtrLessThan(intptr_index, length), &if_oob); 523513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 5236f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if the element is a double hole, but don't load it. 5237f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadFixedDoubleArrayElement(elements, intptr_index, MachineType::None(), 0, 5238f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch INTPTR_PARAMETERS, if_not_found); 5239f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(if_found); 524013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 524113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_isdictionary); 524213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 5243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Negative keys must be converted to property names. 5244c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout); 5245c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5246f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_entry(this, MachineType::PointerRepresentation()); 524713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* elements = LoadElements(object); 5248f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch NumberDictionaryLookup<SeededNumberDictionary>( 5249f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch elements, intptr_index, if_found, &var_entry, if_not_found); 525013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 525113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_isfaststringwrapper); 525213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 5253c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, HasInstanceType(object, JS_VALUE_TYPE)); 525413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* string = LoadJSValueValue(object); 5255c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(string))); 525613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* length = LoadStringLength(string); 5257f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); 525813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_isobjectorsmi); 525913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 526013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Bind(&if_isslowstringwrapper); 526113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 5262c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, HasInstanceType(object, JS_VALUE_TYPE)); 526313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* string = LoadJSValueValue(object); 5264c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(string))); 526513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* length = LoadStringLength(string); 5266f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); 526713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Goto(&if_isdictionary); 526813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 5269f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_oob); 5270f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 5271f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Positive OOB indices mean "not found", negative indices must be 5272f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // converted to property names. 5273f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout); 5274f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(if_not_found); 5275f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 5277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 527813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Instantiate template methods to workaround GCC compilation issue. 527913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>( 528013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node*, Node*, Label*, Variable*, Label*); 528113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate void CodeStubAssembler::NumberDictionaryLookup< 528213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*); 528313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 5284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CodeStubAssembler::TryPrototypeChainLookup( 528562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* receiver, Node* key, const LookupInHolder& lookup_property_in_holder, 528662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const LookupInHolder& lookup_element_in_holder, Label* if_end, 5287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label* if_bailout) { 5288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Ensure receiver is JSReceiver, otherwise bailout. 5289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_objectisnotsmi(this); 5290c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(receiver), if_bailout, &if_objectisnotsmi); 5291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_objectisnotsmi); 5292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* map = LoadMap(receiver); 5294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* instance_type = LoadMapInstanceType(map); 5295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 5296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_objectisreceiver(this); 5297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 5298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE); 5299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch( 5300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), 5301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &if_objectisreceiver, if_bailout); 5302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_objectisreceiver); 5303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 5304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5305f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_index(this, MachineType::PointerRepresentation()); 530662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_unique(this, MachineRepresentation::kTagged); 5307f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_keyisindex(this), if_iskeyunique(this); 530962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_unique, 531062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_bailout); 5311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_iskeyunique); 5313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 531462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_holder(this, MachineRepresentation::kTagged, receiver); 531562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_holder_map(this, MachineRepresentation::kTagged, map); 531662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_holder_instance_type(this, MachineRepresentation::kWord32, 531762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch instance_type); 5318f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5319f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* merged_variables[] = {&var_holder, &var_holder_map, 5320f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &var_holder_instance_type}; 5321f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label loop(this, arraysize(merged_variables), merged_variables); 5322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 5323f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&loop); 5324f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 5325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* holder_map = var_holder_map.value(); 5326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* holder_instance_type = var_holder_instance_type.value(); 5327f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label next_proto(this); 5329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch lookup_property_in_holder(receiver, var_holder.value(), holder_map, 533062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch holder_instance_type, var_unique.value(), 533162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &next_proto, if_bailout); 5332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&next_proto); 5333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Bailout if it can be an integer indexed exotic case. 5335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GotoIf( 5336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Word32Equal(holder_instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), 5337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if_bailout); 5338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* proto = LoadMapPrototype(holder_map); 5340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_not_null(this); 5342f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(WordEqual(proto, NullConstant()), if_end, &if_not_null); 5343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_not_null); 5344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* map = LoadMap(proto); 5346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* instance_type = LoadMapInstanceType(map); 5347f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder.Bind(proto); 5349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder_map.Bind(map); 5350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder_instance_type.Bind(instance_type); 5351f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 5352f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 5353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 5354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_keyisindex); 5355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 535662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_holder(this, MachineRepresentation::kTagged, receiver); 535762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_holder_map(this, MachineRepresentation::kTagged, map); 535862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_holder_instance_type(this, MachineRepresentation::kWord32, 535962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch instance_type); 5360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* merged_variables[] = {&var_holder, &var_holder_map, 5362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &var_holder_instance_type}; 5363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label loop(this, arraysize(merged_variables), merged_variables); 5364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 5365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&loop); 5366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 5367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label next_proto(this); 5368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch lookup_element_in_holder(receiver, var_holder.value(), 5369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder_map.value(), 5370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder_instance_type.value(), 5371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_index.value(), &next_proto, if_bailout); 5372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&next_proto); 5373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* proto = LoadMapPrototype(var_holder_map.value()); 5375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_not_null(this); 5377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Branch(WordEqual(proto, NullConstant()), if_end, &if_not_null); 5378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_not_null); 5379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* map = LoadMap(proto); 5381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* instance_type = LoadMapInstanceType(map); 5382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder.Bind(proto); 5384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder_map.Bind(map); 5385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_holder_instance_type.Bind(instance_type); 5386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Goto(&loop); 5387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 5388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 5389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 5390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, 5392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object) { 5393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 5394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label return_false(this), return_true(this), 5395bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return_runtime(this, Label::kDeferred), return_result(this); 5396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5397bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Goto runtime if {object} is a Smi. 5398c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(object), &return_runtime); 5399bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5400bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load map of {object}. 5401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object_map = LoadMap(object); 5402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Lookup the {callable} and {object} map in the global instanceof cache. 5404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Note: This is safe because we clear the global instanceof cache whenever 5405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // we change the prototype of any object. 5406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* instanceof_cache_function = 5407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadRoot(Heap::kInstanceofCacheFunctionRootIndex); 5408bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* instanceof_cache_map = LoadRoot(Heap::kInstanceofCacheMapRootIndex); 5409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 5410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label instanceof_cache_miss(this); 541162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(WordEqual(instanceof_cache_function, callable), 541262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &instanceof_cache_miss); 541362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(WordEqual(instanceof_cache_map, object_map), 541462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &instanceof_cache_miss); 5415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(LoadRoot(Heap::kInstanceofCacheAnswerRootIndex)); 5416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_result); 5417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&instanceof_cache_miss); 5418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 5419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Goto runtime if {callable} is a Smi. 5421c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(callable), &return_runtime); 5422bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5423bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load map of {callable}. 5424bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* callable_map = LoadMap(callable); 5425bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Goto runtime if {callable} is not a JSFunction. 5427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* callable_instance_type = LoadMapInstanceType(callable_map); 542862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot( 5429bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)), 5430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &return_runtime); 5431bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5432bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Goto runtime if {callable} is not a constructor or has 5433bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // a non-instance "prototype". 5434bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* callable_bitfield = LoadMapBitField(callable_map); 543562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot( 5436bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Word32Equal(Word32And(callable_bitfield, 5437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant((1 << Map::kHasNonInstancePrototype) | 5438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch (1 << Map::kIsConstructor))), 5439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(1 << Map::kIsConstructor)), 5440bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &return_runtime); 5441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Get the "prototype" (or initial map) of the {callable}. 5443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* callable_prototype = 5444bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset); 5445bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 5446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label callable_prototype_valid(this); 544762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_callable_prototype(this, MachineRepresentation::kTagged, 544862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch callable_prototype); 5449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Resolve the "prototype" if the {callable} has an initial map. Afterwards 5451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // the {callable_prototype} will be either the JSReceiver prototype object 5452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // or the hole value, which means that no instances of the {callable} were 5453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // created so far and hence we should return false. 5454bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* callable_prototype_instance_type = 5455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadInstanceType(callable_prototype); 545662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot( 5457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)), 5458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &callable_prototype_valid); 5459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_callable_prototype.Bind( 5460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch LoadObjectField(callable_prototype, Map::kPrototypeOffset)); 5461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&callable_prototype_valid); 5462bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&callable_prototype_valid); 5463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch callable_prototype = var_callable_prototype.value(); 5464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 5465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5466bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update the global instanceof cache with the current {object} map and 5467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // {callable}. The cached answer will be set when it is known below. 5468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, callable); 5469bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreRoot(Heap::kInstanceofCacheMapRootIndex, object_map); 5470bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5471bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Loop through the prototype chain looking for the {callable} prototype. 547262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_object_map(this, MachineRepresentation::kTagged, object_map); 5473bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label loop(this, &var_object_map); 5474bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 5475bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&loop); 5476bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 5477bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object_map = var_object_map.value(); 5478bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5479bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the current {object} needs to be access checked. 5480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object_bitfield = LoadMapBitField(object_map); 548162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot( 5482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Word32Equal(Word32And(object_bitfield, 5483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(1 << Map::kIsAccessCheckNeeded)), 5484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Int32Constant(0)), 5485bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &return_runtime); 5486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check if the current {object} is a proxy. 5488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object_instance_type = LoadMapInstanceType(object_map); 5489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)), 5490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &return_runtime); 5491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check the current {object} prototype. 5493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* object_prototype = LoadMapPrototype(object_map); 5494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GotoIf(WordEqual(object_prototype, NullConstant()), &return_false); 549513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GotoIf(WordEqual(object_prototype, callable_prototype), &return_true); 5496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Continue with the prototype. 5498bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_object_map.Bind(LoadMap(object_prototype)); 5499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&loop); 5500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 5501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_true); 5503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(true)); 5504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(BooleanConstant(true)); 5505bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_result); 5506bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5507bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_false); 5508bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(false)); 5509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind(BooleanConstant(false)); 5510bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_result); 5511bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5512bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_runtime); 5513bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 5514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Invalidate the global instanceof cache. 5515bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, SmiConstant(0)); 5516bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Fallback to the runtime implementation. 5517bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var_result.Bind( 5518bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object)); 5519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 5520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Goto(&return_result); 5521bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5522bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Bind(&return_result); 5523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return var_result.value(); 5524bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 5525bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 552662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node, 552762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ElementsKind kind, 552862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterMode mode, 552962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int base_size) { 5530f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int element_size_shift = ElementsKindToShiftSize(kind); 5531bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch int element_size = 1 << element_size_shift; 5532bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; 553362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch intptr_t index = 0; 553462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch bool constant_index = false; 553562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode == SMI_PARAMETERS) { 553662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch element_size_shift -= kSmiShiftBits; 553762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Smi* smi_index; 553862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch constant_index = ToSmiConstant(index_node, smi_index); 553962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (constant_index) index = smi_index->value(); 554062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch index_node = BitcastTaggedToWord(index_node); 554162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 554262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(mode == INTPTR_PARAMETERS); 554362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch constant_index = ToIntPtrConstant(index_node, index); 5544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 554562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (constant_index) { 554662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntPtrConstant(base_size + element_size * index); 5547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 5548c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 554962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* shifted_index = 555062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (element_size_shift == 0) 555162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? index_node 555262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : ((element_size_shift > 0) 555362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? WordShl(index_node, IntPtrConstant(element_size_shift)) 555462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : WordShr(index_node, IntPtrConstant(-element_size_shift))); 555562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntPtrAdd(IntPtrConstant(base_size), shifted_index); 5556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 5557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 555862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::LoadFeedbackVectorForStub() { 555962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* function = 556062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset); 556162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* cell = LoadObjectField(function, JSFunction::kFeedbackVectorOffset); 556262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LoadObjectField(cell, Cell::kValueOffset); 556362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 556413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 556562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::UpdateFeedback(Node* feedback, Node* feedback_vector, 556662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* slot_id) { 556762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // This method is used for binary op and compare feedback. These 556862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vector nodes are initialized with a smi 0, so we can simply OR 556962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // our new feedback in place. 557062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* previous_feedback = LoadFixedArrayElement(feedback_vector, slot_id); 557162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* combined_feedback = SmiOr(previous_feedback, feedback); 557262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(feedback_vector, slot_id, combined_feedback, 557362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SKIP_WRITE_BARRIER); 557462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 557513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 557662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::LoadReceiverMap(Node* receiver) { 557762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_receiver_map(this, MachineRepresentation::kTagged); 557862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label load_smi_map(this, Label::kDeferred), load_receiver_map(this), 557962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_result(this); 558013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 558162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map); 558262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&load_smi_map); 558313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 558462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex)); 558562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&if_result); 558613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 558762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&load_receiver_map); 558813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 558962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_receiver_map.Bind(LoadMap(receiver)); 559062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&if_result); 5591f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 559262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_result); 559362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return var_receiver_map.value(); 5594f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5595f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 559662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { 559762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_intptr_key(this, MachineType::PointerRepresentation()); 559862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label done(this, &var_intptr_key), key_is_smi(this); 559962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(key), &key_is_smi); 560062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Try to convert a heap number to a Smi. 560162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsHeapNumberMap(LoadMap(key)), miss); 560262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 560362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = LoadHeapNumberValue(key); 560462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* int_value = RoundFloat64ToInt32(value); 560562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Float64Equal(value, ChangeInt32ToFloat64(int_value)), miss); 560662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_intptr_key.Bind(ChangeInt32ToIntPtr(int_value)); 560762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done); 5608f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5609f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 561062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&key_is_smi); 561162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 561262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_intptr_key.Bind(SmiUntag(key)); 561362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done); 5614f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5615f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 561662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&done); 561762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return var_intptr_key.value(); 5618f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5619f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5620f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, 5621f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value, Label* bailout) { 5622f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Mapped arguments are actual arguments. Unmapped arguments are values added 5623f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // to the arguments object after it was created for the call. Mapped arguments 5624f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // are stored in the context at indexes given by elements[key + 2]. Unmapped 5625f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // arguments are stored as regular indexed properties in the arguments array, 5626f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed 5627f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // look at argument object construction. 5628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 5629f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The sloppy arguments elements array has a special format: 5630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 5631f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 0: context 5632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 1: unmapped arguments array 5633f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 2: mapped_index0, 5634f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 3: mapped_index1, 5635f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // ... 5636f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 5637f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments). 5638f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // If key + 2 >= elements.length then attempt to look in the unmapped 5639f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // arguments array (given by elements[1]) and return the value at key, missing 5640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // to the runtime if the unmapped arguments array is not a fixed array or if 5641f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // key >= unmapped_arguments_array.length. 5642f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // 5643f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value 5644f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // in the unmapped arguments array, as described above. Otherwise, t is a Smi 5645f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // index into the context array given at elements[0]. Return the value at 5646f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // context[t]. 5647f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5648f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool is_load = value == nullptr; 5649f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 565062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(TaggedIsSmi(key), bailout); 5651f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch key = SmiUntag(key); 5652f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(IntPtrLessThan(key, IntPtrConstant(0)), bailout); 5653f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5654f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* elements = LoadElements(receiver); 5655f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* elements_length = LoadAndUntagFixedArrayBaseLength(elements); 5656f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5657f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable var_result(this, MachineRepresentation::kTagged); 5658f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (!is_load) { 5659f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(value); 5660f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5661f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label if_mapped(this), if_unmapped(this), end(this, &var_result); 5662f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* intptr_two = IntPtrConstant(2); 5663f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* adjusted_length = IntPtrSub(elements_length, intptr_two); 5664f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5665f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(UintPtrGreaterThanOrEqual(key, adjusted_length), &if_unmapped); 5666f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 566762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* mapped_index = 566862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadFixedArrayElement(elements, IntPtrAdd(key, intptr_two)); 5669f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(WordEqual(mapped_index, TheHoleConstant()), &if_unmapped, &if_mapped); 5670f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_mapped); 5672f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 5673c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, TaggedIsSmi(mapped_index)); 5674f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch mapped_index = SmiUntag(mapped_index); 567562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* the_context = LoadFixedArrayElement(elements, 0); 5676f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Assert that we can use LoadFixedArrayElement/StoreFixedArrayElement 5677f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // methods for accessing Context. 5678f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize); 5679f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_EQ(Context::SlotOffset(0) + kHeapObjectTag, 5680f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FixedArray::OffsetOfElementAt(0)); 5681f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (is_load) { 568262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = LoadFixedArrayElement(the_context, mapped_index); 5683c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, WordNotEqual(result, TheHoleConstant())); 5684f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(result); 5685f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 568662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(the_context, mapped_index, value); 5687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5688f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 5689f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5691f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&if_unmapped); 5692f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 569362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* backing_store = LoadFixedArrayElement(elements, 1); 5694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(WordNotEqual(LoadMap(backing_store), FixedArrayMapConstant()), 5695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bailout); 5696f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5697f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* backing_store_length = 5698f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadAndUntagFixedArrayBaseLength(backing_store); 5699f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length), bailout); 5700f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5701f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The key falls into unmapped range. 5702f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (is_load) { 570362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = LoadFixedArrayElement(backing_store, key); 5704f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(WordEqual(result, TheHoleConstant()), bailout); 5705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var_result.Bind(result); 5706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 570762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(backing_store, key, value); 5708f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&end); 5710f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5711f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5712f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&end); 5713f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return var_result.value(); 5714f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5715f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5716f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) { 5717f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* native_context = LoadNativeContext(context); 5718f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* script_context_table = 5719f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); 5720f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5721f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int offset = 5722f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; 5723f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return Load(MachineType::AnyTagged(), script_context_table, 5724f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntPtrConstant(offset)); 5725f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5726f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5727f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace { 5728f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5729f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Converts typed array elements kind to a machine representations. 5730f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochMachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) { 5731f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch switch (kind) { 5732f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UINT8_CLAMPED_ELEMENTS: 5733f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UINT8_ELEMENTS: 5734f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case INT8_ELEMENTS: 5735f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return MachineRepresentation::kWord8; 5736f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UINT16_ELEMENTS: 5737f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case INT16_ELEMENTS: 5738f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return MachineRepresentation::kWord16; 5739f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UINT32_ELEMENTS: 5740f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case INT32_ELEMENTS: 5741f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return MachineRepresentation::kWord32; 5742f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case FLOAT32_ELEMENTS: 5743f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return MachineRepresentation::kFloat32; 5744f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case FLOAT64_ELEMENTS: 5745f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return MachineRepresentation::kFloat64; 5746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch default: 5747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch UNREACHABLE(); 5748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return MachineRepresentation::kNone; 5749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5752f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} // namespace 5753f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5754f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, 5755f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* index, Node* value, 5756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ParameterMode mode) { 5757f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsFixedTypedArrayElementsKind(kind)) { 5758f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (kind == UINT8_CLAMPED_ELEMENTS) { 5759c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, 5760c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Word32Equal(value, Word32And(Int32Constant(0xff), value))); 5761f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5762f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); 5763f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); 5764f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreNoWriteBarrier(rep, elements, offset, value); 5765f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return; 5766f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5767f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5768f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch WriteBarrierMode barrier_mode = 5769f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; 5770f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsFastDoubleElementsKind(kind)) { 5771f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Make sure we do not store signalling NaNs into double arrays. 5772f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch value = Float64SilenceNaN(value); 5773f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreFixedDoubleArrayElement(elements, index, value, mode); 5774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 577562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); 5776f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5777f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5778f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5779c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) { 5780c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this); 5781c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* int32_zero = Int32Constant(0); 5782c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* int32_255 = Int32Constant(255); 578362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_value(this, MachineRepresentation::kWord32, int32_value); 5784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); 5785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_value.Bind(int32_zero); 5786c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Int32LessThan(int32_value, int32_zero), &done); 5787c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_value.Bind(int32_255); 5788c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 5789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 5790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_value.value(); 5791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 5792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { 5794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this); 579562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_value(this, MachineRepresentation::kWord32, Int32Constant(0)); 5796c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done); 5797c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_value.Bind(Int32Constant(255)); 5798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done); 5799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 5800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rounded_value = Float64RoundToEven(float64_value); 5801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_value.Bind(TruncateFloat64ToWord32(rounded_value)); 5802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 5803f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5804c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 5805c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_value.value(); 5806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 5807f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochNode* CodeStubAssembler::PrepareValueForWriteToTypedArray( 5809c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* input, ElementsKind elements_kind, Label* bailout) { 5810c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(IsFixedTypedArrayElementsKind(elements_kind)); 5811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5812c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineRepresentation rep; 5813c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (elements_kind) { 5814c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT8_ELEMENTS: 5815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case INT8_ELEMENTS: 5816c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT16_ELEMENTS: 5817c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case INT16_ELEMENTS: 5818c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT32_ELEMENTS: 5819c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case INT32_ELEMENTS: 5820c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case UINT8_CLAMPED_ELEMENTS: 5821c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch rep = MachineRepresentation::kWord32; 5822c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 5823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case FLOAT32_ELEMENTS: 5824c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch rep = MachineRepresentation::kFloat32; 5825c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 5826c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case FLOAT64_ELEMENTS: 5827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch rep = MachineRepresentation::kFloat64; 5828c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 5829c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch default: 5830c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch UNREACHABLE(); 5831c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return nullptr; 5832c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 5833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_result(this, rep); 5835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this, &var_result), if_smi(this); 5836c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(input), &if_smi); 5837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Try to convert a heap number to a Smi. 583862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsHeapNumberMap(LoadMap(input)), bailout); 5839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 5840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value = LoadHeapNumberValue(input); 5841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (rep == MachineRepresentation::kWord32) { 5842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (elements_kind == UINT8_CLAMPED_ELEMENTS) { 5843c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = Float64ToUint8Clamped(value); 5844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 5845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = TruncateFloat64ToWord32(value); 5846f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else if (rep == MachineRepresentation::kFloat32) { 5848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = TruncateFloat64ToFloat32(value); 5849f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 5850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(MachineRepresentation::kFloat64, rep); 5851f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(value); 5853c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 5854c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 5855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_smi); 5857c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 5858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value = SmiToWord32(input); 5859c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (rep == MachineRepresentation::kFloat32) { 5860c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = RoundInt32ToFloat32(value); 5861c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else if (rep == MachineRepresentation::kFloat64) { 5862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = ChangeInt32ToFloat64(value); 5863c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 5864c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(MachineRepresentation::kWord32, rep); 5865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (elements_kind == UINT8_CLAMPED_ELEMENTS) { 5866c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = Int32ToUint8Clamped(value); 5867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 5868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 5869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(value); 5870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&done); 5871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 5872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&done); 5874c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_result.value(); 5875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 5876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, 5878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool is_jsarray, 5879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementsKind elements_kind, 5880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch KeyedAccessStoreMode store_mode, 5881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* bailout) { 5882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* elements = LoadElements(object); 5883c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (IsFastSmiOrObjectElementsKind(elements_kind) && 5884c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 5885c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Bailout in case of COW elements. 5886c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(WordNotEqual(LoadMap(elements), 5887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LoadRoot(Heap::kFixedArrayMapRootIndex)), 5888c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bailout); 5889c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 5890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). 5891c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ParameterMode parameter_mode = INTPTR_PARAMETERS; 5892c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch key = TryToIntptr(key, bailout); 5893c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5894c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (IsFixedTypedArrayElementsKind(elements_kind)) { 5895c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done(this); 5896c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // TODO(ishell): call ToNumber() on value and don't bailout but be careful 5897c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // to call it only once if we decide to bailout because of bounds checks. 5898c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 5899c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = PrepareValueForWriteToTypedArray(value, elements_kind, bailout); 5900f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5901f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // There must be no allocations between the buffer load and 5902f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // and the actual store to backing store, because GC may decide that 5903f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // the buffer is not alive or move the elements. 5904f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(ishell): introduce DisallowHeapAllocationCode scope here. 5905f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5906f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if buffer has been neutered. 5907f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); 590862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsDetachedBuffer(buffer), bailout); 5909f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5910f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Bounds check. 591162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* length = TaggedToParameter( 5912f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadObjectField(object, JSTypedArray::kLengthOffset), parameter_mode); 5913f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5914f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 5915f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Skip the store if we write beyond the length. 591662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IntPtrLessThan(key, length), &done); 5917f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // ... but bailout if the key is negative. 5918f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 5919f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_EQ(STANDARD_STORE, store_mode); 5920f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 592162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(UintPtrLessThan(key, length), bailout); 5922f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5923f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Backing store = external_pointer + base_pointer. 5924f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* external_pointer = 5925f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, 5926f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MachineType::Pointer()); 5927f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* base_pointer = 5928f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); 592962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* backing_store = 593062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrAdd(external_pointer, BitcastTaggedToWord(base_pointer)); 5931f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreElement(backing_store, elements_kind, key, value, parameter_mode); 5932f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&done); 5933f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5934f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&done); 5935f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return; 5936f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5937f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) || 5938f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IsFastDoubleElementsKind(elements_kind)); 5939f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5940f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset) 5941f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch : LoadFixedArrayBaseLength(elements); 594262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch length = TaggedToParameter(length, parameter_mode); 5943f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5944f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // In case value is stored into a fast smi array, assure that the value is 5945f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // a smi before manipulating the backing store. Otherwise the backing store 5946f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // may be left in an invalid state. 5947f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsFastSmiElementsKind(elements_kind)) { 594862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(TaggedIsSmi(value), bailout); 5949f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if (IsFastDoubleElementsKind(elements_kind)) { 5950c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch value = TryTaggedToFloat64(value, bailout); 5951f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5952f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5953f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsGrowStoreMode(store_mode)) { 5954f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch elements = CheckForCapacityGrow(object, elements, elements_kind, length, 5955f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch key, parameter_mode, is_jsarray, bailout); 5956f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 595762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(UintPtrLessThan(key, length), bailout); 5958f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5959f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) && 5960f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IsFastSmiOrObjectElementsKind(elements_kind)) { 5961f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch elements = CopyElementsOnWrite(object, elements, elements_kind, length, 5962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch parameter_mode, bailout); 5963f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5964f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5965f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreElement(elements, elements_kind, key, value, parameter_mode); 5966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 5967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::CheckForCapacityGrow(Node* object, Node* elements, 5969f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind kind, Node* length, 5970f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* key, ParameterMode mode, 5971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool is_js_array, 5972f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* bailout) { 5973f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable checked_elements(this, MachineRepresentation::kTagged); 5974f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label grow_case(this), no_grow_case(this), done(this); 5975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* condition; 5977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsHoleyElementsKind(kind)) { 5978f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch condition = UintPtrGreaterThanOrEqual(key, length); 5979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 5980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch condition = WordEqual(key, length); 5981f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 5982f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch(condition, &grow_case, &no_grow_case); 5983f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5984f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&grow_case); 5985f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 5986f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* current_capacity = 598762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TaggedToParameter(LoadFixedArrayBaseLength(elements), mode); 5988f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5989f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch checked_elements.Bind(elements); 5990f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5991f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label fits_capacity(this); 5992f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(UintPtrLessThan(key, current_capacity), &fits_capacity); 5993f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 5994f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* new_elements = TryGrowElementsCapacity( 5995f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch object, elements, kind, key, current_capacity, mode, bailout); 5996f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 5997f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch checked_elements.Bind(new_elements); 5998f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&fits_capacity); 5999f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6000f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&fits_capacity); 6001f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6002f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (is_js_array) { 6003f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* new_length = IntPtrAdd(key, IntPtrOrSmiConstant(1, mode)); 6004f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(object, JSArray::kLengthOffset, 600562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterToTagged(new_length, mode)); 6006f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6007f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&done); 6008f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6009f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6010f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&no_grow_case); 6011f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 601262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(UintPtrLessThan(key, length), bailout); 6013f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch checked_elements.Bind(elements); 6014f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&done); 6015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&done); 6018f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return checked_elements.value(); 6019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 6020f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6021f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::CopyElementsOnWrite(Node* object, Node* elements, 6022f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ElementsKind kind, Node* length, 6023f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ParameterMode mode, 6024f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* bailout) { 602562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable new_elements_var(this, MachineRepresentation::kTagged, elements); 6026f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label done(this); 6027f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 602862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot( 6029f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch WordEqual(LoadMap(elements), LoadRoot(Heap::kFixedCOWArrayMapRootIndex)), 6030f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &done); 6031f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 603262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* capacity = 603362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TaggedToParameter(LoadFixedArrayBaseLength(elements), mode); 6034f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* new_elements = GrowElementsCapacity(object, elements, kind, kind, 6035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch length, capacity, mode, bailout); 6036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch new_elements_var.Bind(new_elements); 6038f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&done); 6039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6040f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6041f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&done); 6042f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return new_elements_var.value(); 6043f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 6044f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 604562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::TransitionElementsKind(Node* object, Node* map, 604662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ElementsKind from_kind, 604762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ElementsKind to_kind, 604862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch bool is_jsarray, 604962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* bailout) { 6050f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(!IsFastHoleyElementsKind(from_kind) || 6051f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IsFastHoleyElementsKind(to_kind)); 6052f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { 6053f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch TrapAllocationMemento(object, bailout); 6054f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6055f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6056f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { 6057f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("Non-simple map transition"); 6058f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* elements = LoadElements(object); 6059f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6060f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* empty_fixed_array = 6061f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch HeapConstant(isolate()->factory()->empty_fixed_array()); 6062f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6063f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label done(this); 6064f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GotoIf(WordEqual(elements, empty_fixed_array), &done); 6065f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6066f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(ishell): Use OptimalParameterMode(). 6067f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ParameterMode mode = INTPTR_PARAMETERS; 6068f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* elements_length = SmiUntag(LoadFixedArrayBaseLength(elements)); 6069f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* array_length = 6070f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch is_jsarray ? SmiUntag(LoadObjectField(object, JSArray::kLengthOffset)) 6071f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch : elements_length; 6072f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6073f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GrowElementsCapacity(object, elements, from_kind, to_kind, array_length, 6074f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch elements_length, mode, bailout); 6075f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Goto(&done); 6076f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&done); 6077f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6078f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 607962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMap(object, map); 6080f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 6081f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6082f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid CodeStubAssembler::TrapAllocationMemento(Node* object, 6083f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* memento_found) { 6084f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("[ TrapAllocationMemento"); 6085f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label no_memento_found(this); 6086f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label top_check(this), map_check(this); 6087f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6088f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* new_space_top_address = ExternalConstant( 6089f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ExternalReference::new_space_allocation_top_address(isolate())); 6090c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const int kMementoMapOffset = JSArray::kSize; 6091c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const int kMementoLastWordOffset = 6092c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kMementoMapOffset + AllocationMemento::kSize - kPointerSize; 6093f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6094f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Bail out if the object is not in new space. 609562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object_word = BitcastTaggedToWord(object); 609662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object_page = PageFromAddress(object_word); 6097f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 6098c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* page_flags = Load(MachineType::IntPtr(), object_page, 6099c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(Page::kFlagsOffset)); 6100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(WordEqual(WordAnd(page_flags, 6101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(MemoryChunk::kIsInNewSpaceMask)), 6102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(0)), 6103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &no_memento_found); 6104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* memento_last_word = IntPtrAdd( 610762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch object_word, IntPtrConstant(kMementoLastWordOffset - kHeapObjectTag)); 6108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* memento_last_word_page = PageFromAddress(memento_last_word); 6109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* new_space_top = Load(MachineType::Pointer(), new_space_top_address); 6111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* new_space_top_page = PageFromAddress(new_space_top); 6112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6113c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // If the object is in new space, we need to check whether respective 6114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // potential memento object is on the same page as the current top. 6115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(WordEqual(memento_last_word_page, new_space_top_page), &top_check); 6116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The object is on a different page than allocation top. Bail out if the 6118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // object sits on the page boundary as no memento can follow and we cannot 6119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // touch the memory following it. 6120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(object_page, memento_last_word_page), &map_check, 6121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &no_memento_found); 6122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // If top is on the same page as the current object, we need to check whether 6124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // we are below top. 6125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&top_check); 6126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 6127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(UintPtrGreaterThanOrEqual(memento_last_word, new_space_top), 6128c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &no_memento_found, &map_check); 6129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Memento map check. 6132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&map_check); 6133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 6134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* memento_map = LoadObjectField(object, kMementoMapOffset); 6135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Branch( 6136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch WordEqual(memento_map, LoadRoot(Heap::kAllocationMementoMapRootIndex)), 6137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch memento_found, &no_memento_found); 6138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 6139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Bind(&no_memento_found); 6140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment("] TrapAllocationMemento"); 6141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 6142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::PageFromAddress(Node* address) { 6144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return WordAnd(address, IntPtrConstant(~Page::kPageAlignmentMask)); 6145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 6146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::EnumLength(Node* map) { 6148c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsMap(map)); 6149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* bitfield_3 = LoadMapBitField3(map); 6150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* enum_length = DecodeWordFromWord32<Map::EnumLengthBits>(bitfield_3); 6151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return SmiTag(enum_length); 6152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 6153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CodeStubAssembler::CheckEnumCache(Node* receiver, Label* use_cache, 6155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label* use_runtime) { 615662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable current_js_object(this, MachineRepresentation::kTagged, receiver); 6157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 615862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable current_map(this, MachineRepresentation::kTagged, 615962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadMap(current_js_object.value())); 6160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // These variables are updated in the loop below. 6162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* loop_vars[2] = {¤t_js_object, ¤t_map}; 6163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label loop(this, 2, loop_vars), next(this); 6164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if the enum length field is properly initialized, indicating that 6166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // there is an enum cache. 6167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 6168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* invalid_enum_cache_sentinel = 6169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SmiConstant(Smi::FromInt(kInvalidEnumCacheSentinel)); 6170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* enum_length = EnumLength(current_map.value()); 6171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(enum_length, invalid_enum_cache_sentinel), use_runtime, 6172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &loop); 6173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 6174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check that there are no elements. |current_js_object| contains 6176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // the current JS object we've reached through the prototype chain. 6177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&loop); 6178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 6179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label if_elements(this), if_no_elements(this); 6180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* elements = LoadElements(current_js_object.value()); 6181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex); 6182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check that there are no elements. 6183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(elements, empty_fixed_array), &if_no_elements, 6184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_elements); 6185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_elements); 6186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 6187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Second chance, the object may be using the empty slow element 6188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // dictionary. 6189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* slow_empty_dictionary = 6190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LoadRoot(Heap::kEmptySlowElementDictionaryRootIndex); 6191c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordNotEqual(elements, slow_empty_dictionary), use_runtime, 6192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_no_elements); 6193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 6194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&if_no_elements); 6196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 6197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Update map prototype. 6198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch current_js_object.Bind(LoadMapPrototype(current_map.value())); 6199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(current_js_object.value(), NullConstant()), use_cache, 6200c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &next); 6201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 6202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 6203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Bind(&next); 6205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 6206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // For all objects but the receiver, check that the cache is empty. 6207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch current_map.Bind(LoadMap(current_js_object.value())); 6208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* enum_length = EnumLength(current_map.value()); 6209c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* zero_constant = SmiConstant(Smi::kZero); 6210c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(enum_length, zero_constant), &loop, use_runtime); 6211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 6212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 6213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* CodeStubAssembler::CreateAllocationSiteInFeedbackVector( 6215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* feedback_vector, Node* slot) { 6216f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* size = IntPtrConstant(AllocationSite::kSize); 6217f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* site = Allocate(size, CodeStubAssembler::kPretenured); 6218f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 621962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMap(site, AllocationSiteMapConstant()); 622062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* kind = SmiConstant(GetInitialFastElementsKind()); 6221f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(site, AllocationSite::kTransitionInfoOffset, 6222f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch kind); 6223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Unlike literals, constructed arrays don't have nested sites 622562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* zero = SmiConstant(0); 6226f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(site, AllocationSite::kNestedSiteOffset, zero); 6227f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6228f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pretenuring calculation field. 6229f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier(site, AllocationSite::kPretenureDataOffset, 6230f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch zero); 6231f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6232f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pretenuring memento creation count field. 6233f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldNoWriteBarrier( 6234f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch site, AllocationSite::kPretenureCreateCountOffset, zero); 6235f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6236f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Store an empty fixed array for the code dependency. 6237f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectFieldRoot(site, AllocationSite::kDependentCodeOffset, 6238f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Heap::kEmptyFixedArrayRootIndex); 6239f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6240f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Link the object to the allocation site list 6241f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* site_list = ExternalConstant( 6242f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ExternalReference::allocation_sites_list_address(isolate())); 6243f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* next_site = LoadBufferObject(site_list, 0); 6244f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6245f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(mvstanton): This is a store to a weak pointer, which we may want to 6246f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // mark as such in order to skip the write barrier, once we have a unified 6247f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // system for weakness. For now we decided to keep it like this because having 6248f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // an initial write barrier backed store makes this pointer strong until the 6249f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // next GC, and allocation sites are designed to survive several GCs anyway. 6250f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreObjectField(site, AllocationSite::kWeakNextOffset, next_site); 6251f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreNoWriteBarrier(MachineRepresentation::kTagged, site_list, site); 6252f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 625362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(feedback_vector, slot, site, UPDATE_WRITE_BARRIER, 0, 6254f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CodeStubAssembler::SMI_PARAMETERS); 6255f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return site; 6256f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 6257f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 6258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* CodeStubAssembler::CreateWeakCellInFeedbackVector(Node* feedback_vector, 6259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* slot, 6260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value) { 6261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* size = IntPtrConstant(WeakCell::kSize); 6262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* cell = Allocate(size, CodeStubAssembler::kPretenured); 6263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Initialize the WeakCell. 626562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(Heap::RootIsImmortalImmovable(Heap::kWeakCellMapRootIndex)); 626662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(cell, Heap::kWeakCellMapRootIndex); 6267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch StoreObjectField(cell, WeakCell::kValueOffset, value); 6268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch StoreObjectFieldRoot(cell, WeakCell::kNextOffset, 6269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Heap::kTheHoleValueRootIndex); 6270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Store the WeakCell in the feedback vector. 627262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, 0, 6273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CodeStubAssembler::SMI_PARAMETERS); 6274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return cell; 6275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 6276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 627762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::BuildFastLoop( 627862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const CodeStubAssembler::VariableList& vars, Node* start_index, 627962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* end_index, const FastLoopBody& body, int increment, 628062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ParameterMode parameter_mode, IndexAdvanceMode advance_mode) { 628162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineRepresentation index_rep = (parameter_mode == INTPTR_PARAMETERS) 628262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? MachineType::PointerRepresentation() 628362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : MachineRepresentation::kTaggedSigned; 628462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var(this, index_rep, start_index); 6285c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableList vars_copy(vars, zone()); 6286c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch vars_copy.Add(&var, zone()); 6287c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label loop(this, vars_copy); 6288c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label after_loop(this); 6289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Introduce an explicit second check of the termination condition before the 6290c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // loop that helps turbofan generate better code. If there's only a single 6291c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // check, then the CodeStubAssembler forces it to be at the beginning of the 6292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // loop requiring a backwards branch at the end of the loop (it's not possible 6293c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // to force the loop header check at the end of the loop and branch forward to 6294c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // it from the pre-header). The extra branch is slower in the case that the 6295c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // loop actually iterates. 6296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(var.value(), end_index), &after_loop, &loop); 6297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&loop); 6298c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 629962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (advance_mode == IndexAdvanceMode::kPre) { 630062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Increment(var, increment, parameter_mode); 6301c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 630262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch body(var.value()); 630362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (advance_mode == IndexAdvanceMode::kPost) { 630462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Increment(var, increment, parameter_mode); 6305c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6306c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordNotEqual(var.value(), end_index), &loop, &after_loop); 6307c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6308c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&after_loop); 630962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return var.value(); 6310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 6311c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6312c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid CodeStubAssembler::BuildFastFixedArrayForEach( 631362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const CodeStubAssembler::VariableList& vars, Node* fixed_array, 631462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ElementsKind kind, Node* first_element_inclusive, 631562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* last_element_exclusive, const FastFixedArrayForEachBody& body, 6316c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ParameterMode mode, ForEachDirection direction) { 6317c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); 6318c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int32_t first_val; 6319c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool constant_first = ToInt32Constant(first_element_inclusive, first_val); 6320c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int32_t last_val; 6321c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool constent_last = ToInt32Constant(last_element_exclusive, last_val); 6322c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (constant_first && constent_last) { 6323c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int delta = last_val - first_val; 6324c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(delta >= 0); 6325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (delta <= kElementLoopUnrollThreshold) { 6326c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (direction == ForEachDirection::kForward) { 6327c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (int i = first_val; i < last_val; ++i) { 6328c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* index = IntPtrConstant(i); 6329c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset = 6330c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS, 6331c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag); 633262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch body(fixed_array, offset); 6333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6334c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 6335c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (int i = last_val - 1; i >= first_val; --i) { 6336c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* index = IntPtrConstant(i); 6337c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset = 6338c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS, 6339c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag); 634062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch body(fixed_array, offset); 6341c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6342c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6343c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return; 6344c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6345c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6346c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6347c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* start = 6348c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementOffsetFromIndex(first_element_inclusive, kind, mode, 6349c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag); 6350c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* limit = 6351c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ElementOffsetFromIndex(last_element_exclusive, kind, mode, 6352c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag); 6353c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (direction == ForEachDirection::kReverse) std::swap(start, limit); 6354c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6355c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int increment = IsFastDoubleElementsKind(kind) ? kDoubleSize : kPointerSize; 6356c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BuildFastLoop( 635762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vars, start, limit, 635862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [fixed_array, &body](Node* offset) { body(fixed_array, offset); }, 6359c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch direction == ForEachDirection::kReverse ? -increment : increment, 636062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch INTPTR_PARAMETERS, 6361c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch direction == ForEachDirection::kReverse ? IndexAdvanceMode::kPre 6362c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : IndexAdvanceMode::kPost); 6363c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 6364c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 636562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::GotoIfFixedArraySizeDoesntFitInNewSpace( 636662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* element_count, Label* doesnt_fit, int base_size, ParameterMode mode) { 636762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int max_newspace_parameters = 636862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (kMaxRegularHeapObjectSize - base_size) / kPointerSize; 636962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IntPtrOrSmiGreaterThan( 637062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch element_count, IntPtrOrSmiConstant(max_newspace_parameters, mode), 637162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch mode), 637262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch doesnt_fit); 637362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 637462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 637562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::InitializeFieldsWithRoot( 637662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object, Node* start_offset, Node* end_offset, 637762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::RootListIndex root_index) { 637862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch start_offset = IntPtrAdd(start_offset, IntPtrConstant(-kHeapObjectTag)); 637962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch end_offset = IntPtrAdd(end_offset, IntPtrConstant(-kHeapObjectTag)); 638062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* root_value = LoadRoot(root_index); 638162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BuildFastLoop(end_offset, start_offset, 638262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [this, object, root_value](Node* current) { 638362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreNoWriteBarrier(MachineRepresentation::kTagged, object, 638462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch current, root_value); 638562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }, 638662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch -kPointerSize, INTPTR_PARAMETERS, 638762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeStubAssembler::IndexAdvanceMode::kPre); 638862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 6389c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 639062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::BranchIfNumericRelationalComparison( 639162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelationalComparisonMode mode, Node* lhs, Node* rhs, Label* if_true, 639262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_false) { 6393c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label end(this); 6394c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 6395c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6396c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Shared entry for floating point comparison. 6397c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label do_fcmp(this); 6398c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64), 6399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs(this, MachineRepresentation::kFloat64); 6400c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6401c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {lhs} is a Smi or a HeapObject. 6402c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsissmi(this), if_lhsisnotsmi(this); 6403c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); 6404c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6405c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsissmi); 6406c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6407c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 6408c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 6409c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 6410c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6411c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 6412c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6413c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison. 6414c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (mode) { 6415c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThan: 6416c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThan(lhs, rhs, if_true, if_false); 6417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6418c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThanOrEqual: 6419c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThanOrEqual(lhs, rhs, if_true, if_false); 6420c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6421c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThan: 6422c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThan(rhs, lhs, if_true, if_false); 6423c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6424c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThanOrEqual: 6425c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThanOrEqual(rhs, lhs, if_true, if_false); 6426c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6427c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6428c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6429c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6430c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 6431c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 643262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsHeapNumberMap(LoadMap(rhs))); 6433c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} and {rhs} to floating point values, and 6434c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 6435c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(SmiToFloat64(lhs)); 6436c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); 6437c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 6438c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6439c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6440c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6441c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotsmi); 6442c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 644362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsHeapNumberMap(LoadMap(lhs))); 6444c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6445c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 6446c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 6447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 6448c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6449c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 6450c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6451c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} and {rhs} to floating point values, and 6452c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 6453c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); 6454c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(SmiToFloat64(rhs)); 6455c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 6456c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6457c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6458c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 6459c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 646062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsHeapNumberMap(LoadMap(rhs))); 6461c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6462c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} and {rhs} to floating point values, and 6463c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 6464c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); 6465c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); 6466c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 6467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6468c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6469c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6470c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&do_fcmp); 6471c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6472c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the {lhs} and {rhs} floating point values. 6473c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs = var_fcmp_lhs.value(); 6474c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs = var_fcmp_rhs.value(); 6475c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6476c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Perform a fast floating point comparison. 6477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (mode) { 6478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThan: 6479c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64LessThan(lhs, rhs), if_true, if_false); 6480c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6481c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThanOrEqual: 6482c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64LessThanOrEqual(lhs, rhs), if_true, if_false); 6483c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6484c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThan: 6485c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64GreaterThan(lhs, rhs), if_true, if_false); 6486c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6487c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThanOrEqual: 6488c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64GreaterThanOrEqual(lhs, rhs), if_true, if_false); 6489c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6490c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6491c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6492c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 6493c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 649462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::GotoUnlessNumberLessThan(Node* lhs, Node* rhs, 6495c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* if_false) { 6496c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_true(this); 6497c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfNumericRelationalComparison(kLessThan, lhs, rhs, &if_true, if_false); 6498c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_true); 6499c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 6500c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 650162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, 650262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* lhs, Node* rhs, 650362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* context) { 6504c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label return_true(this), return_false(this), end(this); 6505c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 6506c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6507c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Shared entry for floating point comparison. 6508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label do_fcmp(this); 6509c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64), 6510c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs(this, MachineRepresentation::kFloat64); 6511c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6512c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We might need to loop several times due to ToPrimitive and/or ToNumber 6513c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // conversions. 651462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_lhs(this, MachineRepresentation::kTagged, lhs), 651562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_rhs(this, MachineRepresentation::kTagged, rhs); 6516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable* loop_vars[2] = {&var_lhs, &var_rhs}; 6517c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label loop(this, 2, loop_vars); 6518c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6519c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&loop); 6520c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6521c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the current {lhs} and {rhs} values. 6522c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch lhs = var_lhs.value(); 6523c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch rhs = var_rhs.value(); 6524c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6525c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {lhs} is a Smi or a HeapObject. 6526c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsissmi(this), if_lhsisnotsmi(this); 6527c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); 6528c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6529c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsissmi); 6530c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6531c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 6532c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 6533c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 6534c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6535c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 6536c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6537c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison. 6538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (mode) { 6539c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThan: 6540c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThan(lhs, rhs, &return_true, &return_false); 6541c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThanOrEqual: 6543c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThanOrEqual(lhs, rhs, &return_true, &return_false); 6544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6545c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThan: 6546c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThan(rhs, lhs, &return_true, &return_false); 6547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6548c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThanOrEqual: 6549c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfSmiLessThanOrEqual(rhs, lhs, &return_true, &return_false); 6550c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6551c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 6555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of {rhs}. 6557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_map = LoadMap(rhs); 6558c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {rhs} is a HeapNumber. 6560c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred); 6561c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); 6562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnumber); 6564c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6565c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} and {rhs} to floating point values, and 6566c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 6567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(SmiToFloat64(lhs)); 6568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); 6569c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 6570c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6571c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6572c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotnumber); 6573c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6574c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {rhs} to a Number; we don't need to perform the 6575c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // dedicated ToPrimitive(rhs, hint Number) operation, as the 6576c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ToNumber(rhs) will by itself already invoke ToPrimitive with 6577c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // a Number hint. 6578c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::NonNumberToNumber(isolate()); 6579c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(CallStub(callable, context, rhs)); 6580c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6581c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6582c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6583c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6584c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6585c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotsmi); 6586c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6587c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of {lhs}. 6588c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_map = LoadMap(lhs); 6589c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6590c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 6591c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 6592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 6593c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 6595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6596c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {lhs} is a HeapNumber. 6597c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisnumber(this), if_lhsisnotnumber(this, Label::kDeferred); 659862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber); 6599c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnumber); 6601c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6602c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} and {rhs} to floating point values, and 6603c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 6604c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); 6605c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(SmiToFloat64(rhs)); 6606c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 6607c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6608c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotnumber); 6610c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6611c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} to a Number; we don't need to perform the 6612c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // dedicated ToPrimitive(lhs, hint Number) operation, as the 6613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ToNumber(lhs) will by itself already invoke ToPrimitive with 6614c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // a Number hint. 6615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::NonNumberToNumber(isolate()); 6616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(CallStub(callable, context, lhs)); 6617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6618c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6620c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6621c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 6622c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6623c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of {rhs}. 6624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_map = LoadMap(rhs); 6625c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6626c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} is a HeapNumber. 6627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisnumber(this), if_lhsisnotnumber(this); 662862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber); 6629c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6630c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnumber); 6631c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6632c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is also a HeapNumber. 6633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred); 6634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(lhs_map, rhs_map), &if_rhsisnumber, 6635c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotnumber); 6636c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnumber); 6638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6639c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} and {rhs} to floating point values, and 6640c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 6641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); 6642c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); 6643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 6644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotnumber); 6647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6648c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {rhs} to a Number; we don't need to perform 6649c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // dedicated ToPrimitive(rhs, hint Number) operation, as the 6650c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ToNumber(rhs) will by itself already invoke ToPrimitive with 6651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // a Number hint. 6652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::NonNumberToNumber(isolate()); 6653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(CallStub(callable, context, rhs)); 6654c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6656c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotnumber); 6659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the instance type of {lhs}. 6661c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_instance_type = LoadMapInstanceType(lhs_map); 6662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} is a String. 6664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisstring(this), if_lhsisnotstring(this, Label::kDeferred); 6665c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring, 6666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_lhsisnotstring); 6667c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisstring); 6669c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6670c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the instance type of {rhs}. 6671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_instance_type = LoadMapInstanceType(rhs_map); 6672c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6673c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is also a String. 6674c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisstring(this, Label::kDeferred), 6675c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotstring(this, Label::kDeferred); 6676c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, 6677c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotstring); 6678c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6679c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisstring); 6680c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6681c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Both {lhs} and {rhs} are strings. 6682c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (mode) { 6683c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThan: 6684c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(CallStub(CodeFactory::StringLessThan(isolate()), 6685c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch context, lhs, rhs)); 6686c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 6687c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6688c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThanOrEqual: 6689c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind( 6690c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallStub(CodeFactory::StringLessThanOrEqual(isolate()), 6691c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch context, lhs, rhs)); 6692c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 6693c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6694c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThan: 6695c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind( 6696c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallStub(CodeFactory::StringGreaterThan(isolate()), 6697c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch context, lhs, rhs)); 6698c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 6699c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6700c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThanOrEqual: 6701c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind( 6702c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallStub(CodeFactory::StringGreaterThanOrEqual(isolate()), 6703c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch context, lhs, rhs)); 6704c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 6705c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6706c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6707c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6708c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6709c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotstring); 6710c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6711c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is a String, while {rhs} is neither a Number nor a 6712c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // String, so we need to call ToPrimitive(rhs, hint Number) if 6713c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // {rhs} is a receiver or ToNumber(lhs) and ToNumber(rhs) in the 6714c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // other cases. 6715c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 6716c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisreceiver(this, Label::kDeferred), 6717c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotreceiver(this, Label::kDeferred); 6718c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsJSReceiverInstanceType(rhs_instance_type), 6719c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisreceiver, &if_rhsisnotreceiver); 6720c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6721c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisreceiver); 6722c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6723c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {rhs} to a primitive first passing Number hint. 6724c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::NonPrimitiveToPrimitive( 6725c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch isolate(), ToPrimitiveHint::kNumber); 6726c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(CallStub(callable, context, rhs)); 6727c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6728c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6729c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6730c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotreceiver); 6731c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6732c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert both {lhs} and {rhs} to Number. 6733c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::ToNumber(isolate()); 6734c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(CallStub(callable, context, lhs)); 6735c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(CallStub(callable, context, rhs)); 6736c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6737c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6738c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6739c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6740c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6741c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotstring); 6742c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6743c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is neither a Number nor a String, so we need to call 6744c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ToPrimitive(lhs, hint Number) if {lhs} is a receiver or 6745c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ToNumber(lhs) and ToNumber(rhs) in the other cases. 6746c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 6747c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisreceiver(this, Label::kDeferred), 6748c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_lhsisnotreceiver(this, Label::kDeferred); 6749c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsJSReceiverInstanceType(lhs_instance_type), 6750c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_lhsisreceiver, &if_lhsisnotreceiver); 6751c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6752c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisreceiver); 6753c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6754c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {lhs} to a primitive first passing Number hint. 6755c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::NonPrimitiveToPrimitive( 6756c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch isolate(), ToPrimitiveHint::kNumber); 6757c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(CallStub(callable, context, lhs)); 6758c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6759c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6760c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6761c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotreceiver); 6762c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6763c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert both {lhs} and {rhs} to Number. 6764c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::ToNumber(isolate()); 6765c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(CallStub(callable, context, lhs)); 6766c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(CallStub(callable, context, rhs)); 6767c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6768c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6769c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6770c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6771c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6772c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6773c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6774c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6775c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&do_fcmp); 6776c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6777c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the {lhs} and {rhs} floating point values. 6778c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs = var_fcmp_lhs.value(); 6779c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs = var_fcmp_rhs.value(); 6780c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6781c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Perform a fast floating point comparison. 6782c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (mode) { 6783c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThan: 6784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64LessThan(lhs, rhs), &return_true, &return_false); 6785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6786c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kLessThanOrEqual: 6787c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64LessThanOrEqual(lhs, rhs), &return_true, &return_false); 6788c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThan: 6790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64GreaterThan(lhs, rhs), &return_true, &return_false); 6791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case kGreaterThanOrEqual: 6793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64GreaterThanOrEqual(lhs, rhs), &return_true, 6794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &return_false); 6795c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 6796c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6797c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_true); 6800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(true)); 6802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 6803c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6804c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6805c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_false); 6806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(false)); 6808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 6809c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6810c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6811c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&end); 6812c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 6813c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 6814c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace { 6816c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 681762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid GenerateEqual_Same(CodeStubAssembler* assembler, Node* value, 6818c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeStubAssembler::Label* if_equal, 6819c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeStubAssembler::Label* if_notequal) { 6820c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // In case of abstract or strict equality checks, we need additional checks 6821c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // for NaN values because they are not considered equal, even if both the 6822c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // left and the right hand side reference exactly the same value. 6823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6824c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch typedef CodeStubAssembler::Label Label; 6825c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6826c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {value} is a Smi or a HeapObject. 6827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_valueissmi(assembler), if_valueisnotsmi(assembler); 6828c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Branch(assembler->TaggedIsSmi(value), &if_valueissmi, 6829c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_valueisnotsmi); 6830c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6831c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Bind(&if_valueisnotsmi); 6832c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of {value}. 6834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value_map = assembler->LoadMap(value); 6835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6836c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {value} (and therefore {rhs}) is a HeapNumber. 6837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_valueisnumber(assembler), if_valueisnotnumber(assembler); 6838c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Branch(assembler->IsHeapNumberMap(value_map), &if_valueisnumber, 6839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_valueisnotnumber); 6840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Bind(&if_valueisnumber); 6842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6843c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {value} (and therefore {rhs}) to floating point value. 6844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value_value = assembler->LoadHeapNumberValue(value); 6845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the HeapNumber value is a NaN. 6847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->BranchIfFloat64IsNaN(value_value, if_notequal, if_equal); 6848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6849c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Bind(&if_valueisnotnumber); 6851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Goto(if_equal); 6852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6853c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6854c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Bind(&if_valueissmi); 6855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler->Goto(if_equal); 6856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 6857c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} // namespace 6858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6859c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// ES6 section 7.2.12 Abstract Equality Comparison 686062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, 686162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* context) { 6862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // This is a slightly optimized version of Object::Equals represented as 6863c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // scheduled TurboFan graph utilizing the CodeStubAssembler. Whenever you 6864c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // change something functionality wise in here, remember to update the 6865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Object::Equals method as well. 6866c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_equal(this), if_notequal(this), 6868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch do_rhsstringtonumber(this, Label::kDeferred), end(this); 6869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 6870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Shared entry for floating point comparison. 6872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label do_fcmp(this); 6873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64), 6874c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs(this, MachineRepresentation::kFloat64); 6875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We might need to loop several times due to ToPrimitive and/or ToNumber 6877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // conversions. 687862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_lhs(this, MachineRepresentation::kTagged, lhs), 687962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_rhs(this, MachineRepresentation::kTagged, rhs); 6880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable* loop_vars[2] = {&var_lhs, &var_rhs}; 6881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label loop(this, 2, loop_vars); 6882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6883c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&loop); 6884c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6885c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the current {lhs} and {rhs} values. 6886c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch lhs = var_lhs.value(); 6887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch rhs = var_rhs.value(); 6888c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6889c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} and {rhs} refer to the same object. 6890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_same(this), if_notsame(this); 6891c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(lhs, rhs), &if_same, &if_notsame); 6892c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6893c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_same); 6894c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6895c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} and {rhs} reference the exact same value, yet we need special 6896c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // treatment for HeapNumber, as NaN is not equal to NaN. 6897c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GenerateEqual_Same(this, lhs, &if_equal, &if_notequal); 6898c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6899c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6900c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_notsame); 6901c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6902c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} is a Smi or a HeapObject. 6903c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsissmi(this), if_lhsisnotsmi(this); 6904c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); 6905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6906c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsissmi); 6907c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6908c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 6909c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 6910c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 6911c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6912c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 6913c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We have already checked for {lhs} and {rhs} being the same value, so 6914c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if both are Smis when we get here they must not be equal. 6915c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 6916c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6917c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 6918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6919c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of {rhs}. 6920c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_map = LoadMap(rhs); 6921c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6922c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a HeapNumber. 6923c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisnumber(this), if_rhsisnotnumber(this); 692462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); 6925c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6926c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnumber); 6927c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6928c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {lhs} and {rhs} to floating point values, and 6929c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 6930c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(SmiToFloat64(lhs)); 6931c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); 6932c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 6933c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6934c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6935c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotnumber); 6936c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6937c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the instance type of the {rhs}. 6938c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_instance_type = LoadMapInstanceType(rhs_map); 6939c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6940c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {rhs} is a String. 6941c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisstring(this, Label::kDeferred), 6942c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotstring(this); 6943c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, 6944c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotstring); 6945c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6946c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisstring); 6947c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6948c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {rhs} is a String and the {lhs} is a Smi; we need 6949c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // to convert the {rhs} to a Number and compare the output to 6950c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // the Number on the {lhs}. 6951c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_rhsstringtonumber); 6952c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6953c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6954c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotstring); 6955c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6956c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {rhs} is a Boolean. 6957c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisboolean(this), if_rhsisnotboolean(this); 6958c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsBooleanMap(rhs_map), &if_rhsisboolean, 6959c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotboolean); 6960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6961c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisboolean); 6962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6963c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {rhs} is a Boolean, load its number value. 6964c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(LoadObjectField(rhs, Oddball::kToNumberOffset)); 6965c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6966c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6967c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6968c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotboolean); 6969c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6970c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {rhs} is a Receiver. 6971c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 6972c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisreceiver(this, Label::kDeferred), 6973c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotreceiver(this); 6974c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsJSReceiverInstanceType(rhs_instance_type), 6975c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisreceiver, &if_rhsisnotreceiver); 6976c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6977c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisreceiver); 6978c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6979c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {rhs} to a primitive first (passing no hint). 6980c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = 6981c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeFactory::NonPrimitiveToPrimitive(isolate()); 6982c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(CallStub(callable, context, rhs)); 6983c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 6984c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6985c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6986c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotreceiver); 6987c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 6988c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6989c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6990c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6991c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6992c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 6993c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 6994c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotsmi); 6995c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 6996c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 6997c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 6998c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 6999c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7000c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 7001c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7002c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is a HeapObject and the {rhs} is a Smi; swapping {lhs} 7003c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // and {rhs} is not observable and doesn't matter for the result, so 7004c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // we can just swap them and use the Smi handling above (for {lhs} 7005c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // being a Smi). 7006c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(rhs); 7007c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(lhs); 7008c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7009c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7011c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 7012c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7013c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisstring(this), if_lhsisnumber(this), 701462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_lhsissymbol(this), if_lhsisoddball(this), 701562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_lhsisreceiver(this); 7016c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7017c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Both {lhs} and {rhs} are HeapObjects, load their maps 7018c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // and their instance types. 7019c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_map = LoadMap(lhs); 7020c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_map = LoadMap(rhs); 7021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7022c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the instance types of {lhs} and {rhs}. 7023c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_instance_type = LoadMapInstanceType(lhs_map); 7024c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_instance_type = LoadMapInstanceType(rhs_map); 7025c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7026c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Dispatch based on the instance type of {lhs}. 702762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size_t const kNumCases = FIRST_NONSTRING_TYPE + 3; 7028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* case_labels[kNumCases]; 7029c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int32_t case_values[kNumCases]; 7030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { 7031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case_labels[i] = new Label(this); 7032c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case_values[i] = i; 7033c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case_labels[FIRST_NONSTRING_TYPE + 0] = &if_lhsisnumber; 7035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE; 7036c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case_labels[FIRST_NONSTRING_TYPE + 1] = &if_lhsissymbol; 7037c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case_values[FIRST_NONSTRING_TYPE + 1] = SYMBOL_TYPE; 703862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case_labels[FIRST_NONSTRING_TYPE + 2] = &if_lhsisoddball; 703962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case_values[FIRST_NONSTRING_TYPE + 2] = ODDBALL_TYPE; 7040c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Switch(lhs_instance_type, &if_lhsisreceiver, case_values, case_labels, 7041c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch arraysize(case_values)); 7042c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { 7043c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(case_labels[i]); 7044c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_lhsisstring); 7045c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch delete case_labels[i]; 7046c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7047c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7048c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisstring); 7049c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7050c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is also a String. 7051c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisstring(this, Label::kDeferred), 7052c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotstring(this); 7053c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, 7054c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotstring); 7055c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7056c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisstring); 7057c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7058c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Both {lhs} and {rhs} are of type String, just do the 7059c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // string comparison then. 7060c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = (mode == kDontNegateResult) 7061c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ? CodeFactory::StringEqual(isolate()) 7062c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : CodeFactory::StringNotEqual(isolate()); 7063c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(CallStub(callable, context, lhs, rhs)); 7064c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7065c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7066c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7067c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotstring); 7068c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7069c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is a String and the {rhs} is some other HeapObject. 7070c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Swapping {lhs} and {rhs} is not observable and doesn't matter 7071c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // for the result, so we can just swap them and use the String 7072c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // handling below (for {rhs} being a String). 7073c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(rhs); 7074c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(lhs); 7075c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7076c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7077c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7078c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7079c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnumber); 7080c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7081c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is also a HeapNumber. 7082c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisnumber(this), if_rhsisnotnumber(this); 7083c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32Equal(lhs_instance_type, rhs_instance_type), 7084c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnumber, &if_rhsisnotnumber); 7085c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7086c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnumber); 7087c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7088c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {lhs} and {rhs} to floating point values, and 7089c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // perform a floating point comparison. 7090c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); 7091c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); 7092c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_fcmp); 7093c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7094c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7095c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotnumber); 7096c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7097c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is a Number, the {rhs} is some other HeapObject. 7098c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisstring(this, Label::kDeferred), 7099c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotstring(this); 7100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, 7101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotstring); 7102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisstring); 7104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {rhs} is a String and the {lhs} is a HeapNumber; we need 7106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // to convert the {rhs} to a Number and compare the output to 7107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // the Number on the {lhs}. 7108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_rhsstringtonumber); 7109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7110c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7111c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotstring); 7112c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7113c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {rhs} is a JSReceiver. 7114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisreceiver(this), if_rhsisnotreceiver(this); 7115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 7116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsJSReceiverInstanceType(rhs_instance_type), 7117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisreceiver, &if_rhsisnotreceiver); 7118c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisreceiver); 7120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7121c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is a Primitive and the {rhs} is a JSReceiver. 7122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Swapping {lhs} and {rhs} is not observable and doesn't 7123c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // matter for the result, so we can just swap them and use 7124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // the JSReceiver handling below (for {lhs} being a 7125c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // JSReceiver). 7126c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(rhs); 7127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(lhs); 7128c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7129c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotreceiver); 7132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7133c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Boolean. 7134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisboolean(this), if_rhsisnotboolean(this); 7135c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsBooleanMap(rhs_map), &if_rhsisboolean, 7136c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotboolean); 7137c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7138c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisboolean); 7139c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7140c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {rhs} is a Boolean, convert it to a Smi first. 7141c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind( 7142c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LoadObjectField(rhs, Oddball::kToNumberOffset)); 7143c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7145c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotboolean); 7147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7148c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7149c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7152c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisoddball); 7154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7155c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is an Oddball and {rhs} is some other HeapObject. 7156c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisboolean(this), if_lhsisnotboolean(this); 7157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* boolean_map = BooleanMapConstant(); 7158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(lhs_map, boolean_map), &if_lhsisboolean, 7159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_lhsisnotboolean); 7160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7161c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisboolean); 7162c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7163c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is a Boolean, check if {rhs} is also a Boolean. 7164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisboolean(this), if_rhsisnotboolean(this); 7165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(rhs_map, boolean_map), &if_rhsisboolean, 7166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotboolean); 7167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisboolean); 7169c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7170c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Both {lhs} and {rhs} are distinct Boolean values. 7171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7173c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7174c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotboolean); 7175c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert the {lhs} to a Number first. 7177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(LoadObjectField(lhs, Oddball::kToNumberOffset)); 7178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7181c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7182c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotboolean); 7183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is either Null or Undefined; check if the {rhs} is 7185c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // undetectable (i.e. either also Null or Undefined or some 7186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // undetectable JSReceiver). 7187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_bitfield = LoadMapBitField(rhs_map); 7188c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32Equal( 7189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Word32And(rhs_bitfield, 7190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(1 << Map::kIsUndetectable)), 7191c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(0)), 7192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_notequal, &if_equal); 7193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7195c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7196c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsissymbol); 7197c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7198c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {rhs} is a JSReceiver. 7199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisreceiver(this), if_rhsisnotreceiver(this); 7200c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 7201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsJSReceiverInstanceType(rhs_instance_type), 7202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisreceiver, &if_rhsisnotreceiver); 7203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7204c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisreceiver); 7205c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} is a Primitive and the {rhs} is a JSReceiver. 7207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Swapping {lhs} and {rhs} is not observable and doesn't 7208c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // matter for the result, so we can just swap them and use 7209c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // the JSReceiver handling below (for {lhs} being a JSReceiver). 7210c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(rhs); 7211c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(lhs); 7212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7213c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7214c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotreceiver); 7216c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {rhs} is not a JSReceiver and also not the same Symbol 7218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // as the {lhs}, so this is equality check is considered false. 7219c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7221c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7222c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisreceiver); 7224c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the {rhs} is also a JSReceiver. 7226c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisreceiver(this), if_rhsisnotreceiver(this); 7227c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 7228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsJSReceiverInstanceType(rhs_instance_type), 7229c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisreceiver, &if_rhsisnotreceiver); 7230c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7231c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisreceiver); 7232c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Both {lhs} and {rhs} are different JSReceiver references, so 7234c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // this cannot be considered equal. 7235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7236c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7237c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7238c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotreceiver); 7239c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7240c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is Null or Undefined (an undetectable check 7241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // is sufficient here, since we already know that {rhs} is not 7242c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // a JSReceiver). 7243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisundetectable(this), 7244c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotundetectable(this, Label::kDeferred); 7245c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_bitfield = LoadMapBitField(rhs_map); 7246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32Equal( 7247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Word32And(rhs_bitfield, 7248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(1 << Map::kIsUndetectable)), 7249c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(0)), 7250c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotundetectable, &if_rhsisundetectable); 7251c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisundetectable); 7253c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7254c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} is an undetectable JSReceiver. 7255c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_bitfield = LoadMapBitField(lhs_map); 7256c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32Equal( 7257c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Word32And(lhs_bitfield, 7258c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(1 << Map::kIsUndetectable)), 7259c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(0)), 7260c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_notequal, &if_equal); 7261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7262c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7263c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotundetectable); 7264c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7265c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {rhs} is some Primitive different from Null and 7266c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Undefined, need to convert {lhs} to Primitive first. 7267c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = 7268c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeFactory::NonPrimitiveToPrimitive(isolate()); 7269c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_lhs.Bind(CallStub(callable, context, lhs)); 7270c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7271c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7272c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7274c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7275c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7276c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7277c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7278c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&do_rhsstringtonumber); 7279c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7280c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = CodeFactory::StringToNumber(isolate()); 7281c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_rhs.Bind(CallStub(callable, context, rhs)); 7282c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&loop); 7283c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7284c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7285c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7286c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&do_fcmp); 7287c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7288c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the {lhs} and {rhs} floating point values. 7289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs = var_fcmp_lhs.value(); 7290c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs = var_fcmp_rhs.value(); 7291c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Perform a fast floating point comparison. 7293c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64Equal(lhs, rhs), &if_equal, &if_notequal); 7294c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7295c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_equal); 7297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7298c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(mode == kDontNegateResult)); 7299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7300c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7301c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7302c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_notequal); 7303c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7304c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(mode == kNegateResult)); 7305c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7306c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7307c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7308c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&end); 7309c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 7310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7311c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 731262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, 731362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* context) { 7314c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Here's pseudo-code for the algorithm below in case of kDontNegateResult 7315c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // mode; for kNegateResult mode we properly negate the result. 7316c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 7317c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (lhs == rhs) { 7318c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN; 7319c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return true; 7320c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7321c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (!lhs->IsSmi()) { 7322c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (lhs->IsHeapNumber()) { 7323c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (rhs->IsSmi()) { 7324c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return Smi::cast(rhs)->value() == HeapNumber::cast(lhs)->value(); 7325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else if (rhs->IsHeapNumber()) { 7326c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return HeapNumber::cast(rhs)->value() == 7327c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // HeapNumber::cast(lhs)->value(); 7328c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7329c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return false; 7330c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7331c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7332c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (rhs->IsSmi()) { 7333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return false; 7334c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7335c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (lhs->IsString()) { 7336c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (rhs->IsString()) { 7337c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return %StringEqual(lhs, rhs); 7338c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7339c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return false; 7340c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7341c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7342c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return false; 7343c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7344c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7345c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7346c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7347c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (rhs->IsSmi()) { 7348c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return false; 7349c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7350c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if (rhs->IsHeapNumber()) { 7351c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return Smi::cast(lhs)->value() == HeapNumber::cast(rhs)->value(); 7352c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } else { 7353c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // return false; 7354c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7355c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7356c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // } 7357c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7358c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_equal(this), if_notequal(this), end(this); 7359c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 7360c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7361c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} and {rhs} refer to the same object. 7362c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_same(this), if_notsame(this); 7363c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(lhs, rhs), &if_same, &if_notsame); 7364c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7365c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_same); 7366c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7367c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {lhs} and {rhs} reference the exact same value, yet we need special 7368c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // treatment for HeapNumber, as NaN is not equal to NaN. 7369c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GenerateEqual_Same(this, lhs, &if_equal, &if_notequal); 7370c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7371c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7372c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_notsame); 7373c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 737462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber 737562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // and String they can still be considered equal. 7376c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7377c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} is a Smi or a HeapObject. 7378c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsissmi(this), if_lhsisnotsmi(this); 7379c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); 7380c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7381c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotsmi); 7382c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7383c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of {lhs}. 7384c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_map = LoadMap(lhs); 7385c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7386c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} is a HeapNumber. 7387c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisnumber(this), if_lhsisnotnumber(this); 738862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber); 7389c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7390c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnumber); 7391c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7392c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 7393c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 7394c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 7395c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7396c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 7397c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7398c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {lhs} and {rhs} to floating point values. 7399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_value = LoadHeapNumberValue(lhs); 7400c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_value = SmiToFloat64(rhs); 7401c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7402c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Perform a floating point comparison of {lhs} and {rhs}. 7403c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal); 7404c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7405c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7406c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 7407c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7408c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of {rhs}. 7409c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_map = LoadMap(rhs); 7410c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7411c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is also a HeapNumber. 7412c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisnumber(this), if_rhsisnotnumber(this); 741362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); 7414c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7415c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnumber); 7416c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {lhs} and {rhs} to floating point values. 7418c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_value = LoadHeapNumberValue(lhs); 7419c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_value = LoadHeapNumberValue(rhs); 7420c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7421c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Perform a floating point comparison of {lhs} and {rhs}. 7422c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal); 7423c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7424c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7425c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotnumber); 7426c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7427c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7428c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7429c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7430c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotnumber); 7431c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7432c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 7433c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 7434c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 7435c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7436c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 7437c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7438c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7439c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 7440c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7441c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the instance type of {lhs}. 7442c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_instance_type = LoadMapInstanceType(lhs_map); 7443c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7444c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {lhs} is a String. 7445c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisstring(this), if_lhsisnotstring(this); 7446c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring, 7447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_lhsisnotstring); 7448c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7449c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisstring); 7450c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7451c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the instance type of {rhs}. 7452c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_instance_type = LoadInstanceType(rhs); 7453c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7454c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is also a String. 7455c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisstring(this, Label::kDeferred), 7456c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_rhsisnotstring(this); 7457c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, 7458c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_rhsisnotstring); 7459c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7460c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisstring); 7461c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7462c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Callable callable = (mode == kDontNegateResult) 7463c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ? CodeFactory::StringEqual(isolate()) 7464c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : CodeFactory::StringNotEqual(isolate()); 7465c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(CallStub(callable, context, lhs, rhs)); 7466c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7468c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7469c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotstring); 7470c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7471c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7472c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7473c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnotstring); 747462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&if_notequal); 7475c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7476c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7479c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsissmi); 7480c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7481c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We already know that {lhs} and {rhs} are not reference equal, and {lhs} 7482c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a 7483c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // HeapNumber with an equal floating point value. 7484c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7485c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if {rhs} is a Smi or a HeapObject. 7486c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsissmi(this), if_rhsisnotsmi(this); 7487c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); 7488c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7489c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsissmi); 7490c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7491c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7492c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotsmi); 7493c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7494c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the map of the {rhs}. 7495c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_map = LoadMap(rhs); 7496c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7497c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // The {rhs} could be a HeapNumber with the same value as {lhs}. 7498c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_rhsisnumber(this), if_rhsisnotnumber(this); 749962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); 7500c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7501c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnumber); 7502c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7503c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Convert {lhs} and {rhs} to floating point values. 7504c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* lhs_value = SmiToFloat64(lhs); 7505c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* rhs_value = LoadHeapNumberValue(rhs); 7506c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7507c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Perform a floating point comparison of {lhs} and {rhs}. 7508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal); 7509c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7510c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7511c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_rhsisnotnumber); 7512c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&if_notequal); 7513c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7514c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7515c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7517c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_equal); 7518c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7519c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(mode == kDontNegateResult)); 7520c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7521c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7522c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7523c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_notequal); 7524c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7525c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(mode == kNegateResult)); 7526c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7527c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7528c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7529c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&end); 7530c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 7531c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7532c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7533c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// ECMA#sec-samevalue 7534c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// This algorithm differs from the Strict Equality Comparison Algorithm in its 7535c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// treatment of signed zeroes and NaNs. 753662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { 753762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_result(this, MachineRepresentation::kWord32); 7538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label strict_equal(this), out(this); 7539c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 754062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const int_false = Int32Constant(0); 754162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const int_true = Int32Constant(1); 7542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7543c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_equal(this), if_notequal(this); 7544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(lhs, rhs), &if_equal, &if_notequal); 7545c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7546c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_equal); 7547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7548c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // This covers the case when {lhs} == {rhs}. We can simply return true 7549c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // because SameValue considers two NaNs to be equal. 7550c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7551c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(int_true); 7552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&out); 7553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_notequal); 7556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // This covers the case when {lhs} != {rhs}. We only handle numbers here 7558c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // and defer to StrictEqual for the rest. 7559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7560c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const lhs_float = TryTaggedToFloat64(lhs, &strict_equal); 7561c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const rhs_float = TryTaggedToFloat64(rhs, &strict_equal); 7562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_lhsisnan(this), if_lhsnotnan(this); 7564c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BranchIfFloat64IsNaN(lhs_float, &if_lhsisnan, &if_lhsnotnan); 7565c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7566c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsisnan); 7567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Return true iff {rhs} is NaN. 7569c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7570c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const result = 757162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SelectConstant(Float64Equal(rhs_float, rhs_float), int_false, 757262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int_true, MachineRepresentation::kWord32); 7573c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(result); 7574c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&out); 7575c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7576c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7577c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_lhsnotnan); 7578c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7579c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_floatisequal(this), if_floatnotequal(this); 7580c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Float64Equal(lhs_float, rhs_float), &if_floatisequal, 7581c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_floatnotequal); 7582c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7583c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_floatisequal); 7584c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7585c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We still need to handle the case when {lhs} and {rhs} are -0.0 and 7586c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 0.0 (or vice versa). Compare the high word to 7587c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // distinguish between the two. 7588c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7589c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const lhs_hi_word = Float64ExtractHighWord32(lhs_float); 7590c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const rhs_hi_word = Float64ExtractHighWord32(rhs_float); 7591c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // If x is +0 and y is -0, return false. 7593c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // If x is -0 and y is +0, return false. 7594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const result = Word32Equal(lhs_hi_word, rhs_hi_word); 7596c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(result); 7597c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&out); 7598c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7599c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_floatnotequal); 7601c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7602c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(int_false); 7603c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&out); 7604c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7605c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7606c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7607c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7608c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&strict_equal); 7609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7610c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const is_equal = StrictEqual(kDontNegateResult, lhs, rhs, context); 7611c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const result = WordEqual(is_equal, TrueConstant()); 7612c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(result); 7613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&out); 7614c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&out); 7617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_result.value(); 7618c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 762062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::ForInFilter(Node* key, Node* object, Node* context) { 7621c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label return_undefined(this, Label::kDeferred), return_to_name(this), 7622c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch end(this); 7623c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); 7625c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7626c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* has_property = 7627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch HasProperty(object, key, context, Runtime::kForInHasProperty); 7628c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7629c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(WordEqual(has_property, BooleanConstant(true)), &return_to_name, 7630c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &return_undefined); 7631c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7632c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_to_name); 7633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(ToName(context, key)); 7635c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7636c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_undefined); 7639c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7640c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(UndefinedConstant()); 7641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7642c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&end); 7645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_result.value(); 7646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 764862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::HasProperty( 764962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object, Node* key, Node* context, 7650c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Runtime::FunctionId fallback_runtime_function_id) { 7651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label call_runtime(this, Label::kDeferred), return_true(this), 7652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return_false(this), end(this); 7653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7654c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeStubAssembler::LookupInHolder lookup_property_in_holder = 7655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch [this, &return_true](Node* receiver, Node* holder, Node* holder_map, 7656c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* holder_instance_type, Node* unique_name, 7657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* next_holder, Label* if_bailout) { 7658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TryHasOwnProperty(holder, holder_map, holder_instance_type, unique_name, 7659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &return_true, next_holder, if_bailout); 7660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch }; 7661c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeStubAssembler::LookupInHolder lookup_element_in_holder = 7663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch [this, &return_true](Node* receiver, Node* holder, Node* holder_map, 7664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* holder_instance_type, Node* index, 7665c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* next_holder, Label* if_bailout) { 7666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TryLookupElement(holder, holder_map, holder_instance_type, index, 7667c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &return_true, next_holder, if_bailout); 7668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch }; 7669c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7670c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TryPrototypeChainLookup(object, key, lookup_property_in_holder, 7671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch lookup_element_in_holder, &return_false, 7672c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &call_runtime); 7673c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7674c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result(this, MachineRepresentation::kTagged); 7675c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_true); 7676c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7677c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(true)); 7678c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7679c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7680c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7681c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_false); 7682c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7683c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind(BooleanConstant(false)); 7684c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7685c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7686c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7687c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&call_runtime); 7688c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7689c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result.Bind( 7690c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallRuntime(fallback_runtime_function_id, context, object, key)); 7691c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7692c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7693c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7694c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&end); 7695c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 7696c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7697c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 769862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::ClassOf(Node* value) { 769962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_result(this, MachineRepresentation::kTaggedPointer); 770062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_function(this, Label::kDeferred), if_object(this, Label::kDeferred), 770162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_primitive(this, Label::kDeferred), return_result(this); 770262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 770362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if {value} is a Smi. 770462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(value), &if_primitive); 770562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 770662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = LoadMap(value); 770762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_instance_type = LoadMapInstanceType(value_map); 770862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 770962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if {value} is a JSFunction or JSBoundFunction. 771062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE); 771162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Uint32LessThanOrEqual(Int32Constant(FIRST_FUNCTION_TYPE), 771262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value_instance_type), 771362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_function); 771462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 771562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if {value} is a primitive HeapObject. 771662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 771762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(Uint32LessThan(value_instance_type, 771862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Int32Constant(FIRST_JS_RECEIVER_TYPE)), 771962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_primitive); 772062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 772162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Load the {value}s constructor, and check that it's a JSFunction. 772262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* constructor = LoadMapConstructor(value_map); 772362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsJSFunction(constructor), &if_object); 772462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 772562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Return the instance class name for the {constructor}. 772662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* shared_info = 772762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(constructor, JSFunction::kSharedFunctionInfoOffset); 772862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* instance_class_name = LoadObjectField( 772962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch shared_info, SharedFunctionInfo::kInstanceClassNameOffset); 773062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(instance_class_name); 773162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 773262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 773362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_function); 773462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(LoadRoot(Heap::kFunction_stringRootIndex)); 773562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 773662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 773762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_object); 773862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(LoadRoot(Heap::kObject_stringRootIndex)); 773962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 774062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 774162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_primitive); 774262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(NullConstant()); 774362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 774462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 774562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&return_result); 774662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return var_result.value(); 774762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 774862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 774962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::Typeof(Node* value, Node* context) { 7750c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable result_var(this, MachineRepresentation::kTagged); 7751c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7752c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label return_number(this, Label::kDeferred), if_oddball(this), 7753c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return_function(this), return_undefined(this), return_object(this), 7754c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return_string(this), return_result(this); 7755c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7756c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(TaggedIsSmi(value), &return_number); 7757c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7758c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* map = LoadMap(value); 7759c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7760c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(IsHeapNumberMap(map), &return_number); 7761c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7762c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* instance_type = LoadMapInstanceType(map); 7763c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7764c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE)), &if_oddball); 7765c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7766c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* callable_or_undetectable_mask = Word32And( 7767c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LoadMapBitField(map), 7768c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(1 << Map::kIsCallable | 1 << Map::kIsUndetectable)); 7769c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7770c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(Word32Equal(callable_or_undetectable_mask, 7771c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(1 << Map::kIsCallable)), 7772c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &return_function); 7773c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 777462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(Word32Equal(callable_or_undetectable_mask, Int32Constant(0)), 777562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &return_undefined); 7776c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7777c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(IsJSReceiverInstanceType(instance_type), &return_object); 7778c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7779c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GotoIf(IsStringInstanceType(instance_type), &return_string); 7780c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7781c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, Word32Equal(instance_type, Int32Constant(SYMBOL_TYPE))); 7782c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result_var.Bind(HeapConstant(isolate()->factory()->symbol_string())); 7783c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 7784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_number); 7786c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7787c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result_var.Bind(HeapConstant(isolate()->factory()->number_string())); 7788c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 7789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_oddball); 7792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* type = LoadObjectField(value, Oddball::kTypeOfOffset); 7794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result_var.Bind(type); 7795c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 7796c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7797c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_function); 7799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result_var.Bind(HeapConstant(isolate()->factory()->function_string())); 7801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 7802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7803c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7804c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_undefined); 7805c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result_var.Bind(HeapConstant(isolate()->factory()->undefined_string())); 7807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 7808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7809c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7810c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_object); 7811c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7812c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result_var.Bind(HeapConstant(isolate()->factory()->object_string())); 7813c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 7814c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7816c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_string); 7817c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7818c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result_var.Bind(HeapConstant(isolate()->factory()->string_string())); 7819c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 7820c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7821c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7822c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_result); 7823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result_var.value(); 7824c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7825c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 782662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::GetSuperConstructor(Node* active_function, 782762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* context) { 782862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsJSFunction(active_function)); 7829c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 783062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label is_not_constructor(this, Label::kDeferred), out(this); 783162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable result(this, MachineRepresentation::kTagged); 7832c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 783362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* map = LoadMap(active_function); 783462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* prototype = LoadMapPrototype(map); 783562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* prototype_map = LoadMap(prototype); 783662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsConstructorMap(prototype_map), &is_not_constructor); 7837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 783862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result.Bind(prototype); 783962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&out); 7840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 784162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&is_not_constructor); 7842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 784362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime(Runtime::kThrowNotSuperConstructor, context, prototype, 784462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch active_function); 784562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unreachable(); 7846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 784862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&out); 7849c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result.value(); 7850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 785262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::InstanceOf(Node* object, Node* callable, 785362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* context) { 785462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); 785562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_notcallable(this, Label::kDeferred), 785662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_notreceiver(this, Label::kDeferred), if_otherhandler(this), 785762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_nohandler(this, Label::kDeferred), return_true(this), 785862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return_false(this), return_result(this, &var_result); 785962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 786062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Ensure that the {callable} is actually a JSReceiver. 786162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(callable), &if_notreceiver); 786262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsJSReceiver(callable), &if_notreceiver); 786362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 786462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Load the @@hasInstance property from {callable}. 786562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* inst_of_handler = CallStub(CodeFactory::GetProperty(isolate()), context, 786662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch callable, HasInstanceSymbolConstant()); 786762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 786862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Optimize for the likely case where {inst_of_handler} is the builtin 786962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Function.prototype[@@hasInstance] method, and emit a direct call in 787062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // that case without any additional checking. 787162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* native_context = LoadNativeContext(context); 787262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* function_has_instance = 787362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadContextElement(native_context, Context::FUNCTION_HAS_INSTANCE_INDEX); 787462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(WordEqual(inst_of_handler, function_has_instance), 787562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_otherhandler); 787662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 787762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Call to Function.prototype[@@hasInstance] directly. 787862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable builtin(isolate()->builtins()->FunctionPrototypeHasInstance(), 787962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallTrampolineDescriptor(isolate())); 788062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = CallJS(builtin, context, inst_of_handler, callable, object); 788162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(result); 788262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 788362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 788462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 788562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_otherhandler); 788662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 788762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if there's actually an {inst_of_handler}. 788862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsNull(inst_of_handler), &if_nohandler); 788962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsUndefined(inst_of_handler), &if_nohandler); 789062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 789162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Call the {inst_of_handler} for {callable} and {object}. 789262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = CallJS( 789362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined), 789462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch context, inst_of_handler, callable, object); 789562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 789662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Convert the {result} to a Boolean. 789762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BranchIfToBooleanIsTrue(result, &return_true, &return_false); 789862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 789962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 790062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_nohandler); 790162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 790262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Ensure that the {callable} is actually Callable. 790362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsCallable(callable), &if_notcallable); 790462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 790562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Use the OrdinaryHasInstance algorithm. 790662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = CallStub(CodeFactory::OrdinaryHasInstance(isolate()), 790762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch context, callable, object); 790862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(result); 790962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 791062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 791162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 791262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_notcallable); 791362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 791462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime(Runtime::kThrowNonCallableInInstanceOfCheck, context); 791562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unreachable(); 791662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 791762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 791862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_notreceiver); 791962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 792062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime(Runtime::kThrowNonObjectInInstanceOfCheck, context); 792162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unreachable(); 792262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 792362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 792462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&return_true); 792562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(TrueConstant()); 792662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 792762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 792862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&return_false); 792962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(FalseConstant()); 793062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&return_result); 793162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 793262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&return_result); 793362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return var_result.value(); 793462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 793562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 793662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::NumberInc(Node* value) { 7937c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_result(this, MachineRepresentation::kTagged), 7938c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_finc_value(this, MachineRepresentation::kFloat64); 7939c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_issmi(this), if_isnotsmi(this), do_finc(this), end(this); 7940c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi); 7941c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7942c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_issmi); 7943c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7944c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Try fast Smi addition first. 7945c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* one = SmiConstant(Smi::FromInt(1)); 7946c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(value), 7947c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BitcastTaggedToWord(one)); 7948c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* overflow = Projection(1, pair); 7949c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7950c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the Smi addition overflowed. 7951c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_overflow(this), if_notoverflow(this); 7952c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(overflow, &if_overflow, &if_notoverflow); 7953c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7954c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_notoverflow); 795562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair))); 7956c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7957c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7958c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_overflow); 7959c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_finc_value.Bind(SmiToFloat64(value)); 7961c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_finc); 7962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7963c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7964c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7965c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isnotsmi); 7966c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7967c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if the value is a HeapNumber. 7968c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsHeapNumberMap(LoadMap(value))); 7969c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7970c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the HeapNumber value. 7971c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_finc_value.Bind(LoadHeapNumberValue(value)); 7972c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&do_finc); 7973c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7974c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7975c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&do_finc); 7976c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 7977c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* finc_value = var_finc_value.value(); 7978c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* one = Float64Constant(1.0); 7979c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* finc_result = Float64Add(finc_value, one); 7980c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(AllocateHeapNumberWithValue(finc_result)); 7981c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&end); 7982c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 7983c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 7984c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&end); 7985c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_result.value(); 7986c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 7987c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 798862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::GotoIfNotNumber(Node* input, Label* is_not_number) { 798962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label is_number(this); 799062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(input), &is_number); 799162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* input_map = LoadMap(input); 799262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsHeapNumberMap(input_map), &is_number, is_not_number); 799362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&is_number); 799462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 799562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 799662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::GotoIfNumber(Node* input, Label* is_number) { 799762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(input), is_number); 799862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* input_map = LoadMap(input); 799962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(IsHeapNumberMap(input_map), is_number); 800062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 800162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 800262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, 800362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* array_type, Node* context, 800462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IterationKind mode) { 8005c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int kBaseMapIndex = 0; 8006c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch switch (mode) { 8007c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case IterationKind::kKeys: 8008c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kBaseMapIndex = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX; 8009c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 8010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case IterationKind::kValues: 8011c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kBaseMapIndex = Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX; 8012c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 8013c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case IterationKind::kEntries: 8014c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kBaseMapIndex = Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX; 8015c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 8016c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8017c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8018c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Fast Array iterator map index: 8019c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // (kBaseIndex + kFastIteratorOffset) + ElementsKind (for JSArrays) 8020c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // kBaseIndex + (ElementsKind - UINT8_ELEMENTS) (for JSTypedArrays) 8021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const int kFastIteratorOffset = 8022c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX - 8023c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX; 8024c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(kFastIteratorOffset == 8025c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX - 8026c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX)); 8027c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Slow Array iterator map index: (kBaseIndex + kSlowIteratorOffset) 8029c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const int kSlowIteratorOffset = 8030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX - 8031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX; 8032c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(kSlowIteratorOffset == 8033c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX - 8034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX)); 8035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8036c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Assert: Type(array) is Object 8037c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsJSReceiverInstanceType(array_type)); 8038c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8039c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_result(this, MachineRepresentation::kTagged); 8040c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_map_index(this, MachineType::PointerRepresentation()); 8041c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Variable var_array_map(this, MachineRepresentation::kTagged); 8042c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8043c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label return_result(this); 8044c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label allocate_iterator(this); 8045c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8046c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (mode == IterationKind::kKeys) { 8047c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // There are only two key iterator maps, branch depending on whether or not 8048c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // the receiver is a TypedArray or not. 8049c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8050c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_istypedarray(this), if_isgeneric(this); 8051c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8052c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), 8053c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_istypedarray, &if_isgeneric); 8054c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8055c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isgeneric); 8056c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8057c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_isfast(this), if_isslow(this); 805862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, 805962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_isfast, &if_isslow); 8060c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8061c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isfast); 8062c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8063c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_map_index.Bind( 8064c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX)); 8065c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_array_map.Bind(array_map); 8066c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&allocate_iterator); 8067c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8068c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8069c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isslow); 8070c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8071c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_map_index.Bind( 8072c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX)); 8073c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_array_map.Bind(UndefinedConstant()); 8074c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&allocate_iterator); 8075c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8076c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8077c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8078c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_istypedarray); 8079c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8080c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_map_index.Bind( 8081c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX)); 8082c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_array_map.Bind(UndefinedConstant()); 8083c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&allocate_iterator); 8084c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8085c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 8086c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_istypedarray(this), if_isgeneric(this); 8087c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), 8088c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_istypedarray, &if_isgeneric); 8089c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8090c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isgeneric); 8091c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8092c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_isfast(this), if_isslow(this); 809362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, 809462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_isfast, &if_isslow); 8095c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8096c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isfast); 8097c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8098c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label if_ispacked(this), if_isholey(this); 8099c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* elements_kind = LoadMapElementsKind(array_map); 8100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsHoleyFastElementsKind(elements_kind), &if_isholey, 8101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_ispacked); 8102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isholey); 8104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Fast holey JSArrays can treat the hole as undefined if the 8106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // protector cell is valid, and the prototype chain is unchanged from 8107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // its initial state (because the protector cell is only tracked for 8108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // initial the Array and Object prototypes). Check these conditions 8109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // here, and take the slow path if any fail. 8110c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); 8111c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); 811262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot( 8113c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch WordEqual( 8114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LoadObjectField(protector_cell, PropertyCell::kValueOffset), 8115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), 8116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &if_isslow); 8117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8118c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* native_context = LoadNativeContext(context); 8119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* prototype = LoadMapPrototype(array_map); 8121c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* array_prototype = LoadContextElement( 8122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch native_context, Context::INITIAL_ARRAY_PROTOTYPE_INDEX); 812362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(WordEqual(prototype, array_prototype), &if_isslow); 8124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8125c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* map = LoadMap(prototype); 8126c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch prototype = LoadMapPrototype(map); 8127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* object_prototype = LoadContextElement( 8128c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch native_context, Context::INITIAL_OBJECT_PROTOTYPE_INDEX); 812962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(WordEqual(prototype, object_prototype), &if_isslow); 8130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch map = LoadMap(prototype); 8132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch prototype = LoadMapPrototype(map); 8133c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Branch(IsNull(prototype), &if_ispacked, &if_isslow); 8134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8135c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_ispacked); 8136c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8137c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* map_index = 8138c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset), 813962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ChangeUint32ToWord(LoadMapElementsKind(array_map))); 8140c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IntPtrGreaterThanOrEqual( 8141c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch map_index, IntPtrConstant(kBaseMapIndex + 8142c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kFastIteratorOffset))); 8143c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IntPtrLessThan(map_index, 8144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(kBaseMapIndex + 8145c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kSlowIteratorOffset))); 8146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_map_index.Bind(map_index); 8148c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_array_map.Bind(array_map); 8149c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&allocate_iterator); 8150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8152c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_isslow); 8154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8155c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex), 8156c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(kSlowIteratorOffset)); 8157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_map_index.Bind(map_index); 8158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_array_map.Bind(UndefinedConstant()); 8159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&allocate_iterator); 8160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8161c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8162c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8163c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&if_istypedarray); 8164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 8165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* map_index = 8166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrAdd(IntPtrConstant(kBaseMapIndex - UINT8_ELEMENTS), 816762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ChangeUint32ToWord(LoadMapElementsKind(array_map))); 8168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT( 8169c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch this, IntPtrLessThan(map_index, IntPtrConstant(kBaseMapIndex + 8170c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kFastIteratorOffset))); 8171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IntPtrGreaterThanOrEqual(map_index, 8172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntPtrConstant(kBaseMapIndex))); 8173c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_map_index.Bind(map_index); 8174c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_array_map.Bind(UndefinedConstant()); 8175c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&allocate_iterator); 8176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&allocate_iterator); 8180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 818162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* map = LoadFixedArrayElement(LoadNativeContext(context), 818262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_map_index.value()); 8183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var_result.Bind(AllocateJSArrayIterator(array, var_array_map.value(), map)); 8184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Goto(&return_result); 8185c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Bind(&return_result); 8188c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_result.value(); 8189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 819162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::AllocateJSArrayIterator(Node* array, Node* array_map, 819262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* map) { 8193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* iterator = Allocate(JSArrayIterator::kSize); 8194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreMapNoWriteBarrier(iterator, map); 8195c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldRoot(iterator, JSArrayIterator::kPropertiesOffset, 8196c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Heap::kEmptyFixedArrayRootIndex); 8197c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldRoot(iterator, JSArrayIterator::kElementsOffset, 8198c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Heap::kEmptyFixedArrayRootIndex); 8199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(iterator, 8200c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch JSArrayIterator::kIteratedObjectOffset, array); 8201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset, 8202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SmiConstant(Smi::FromInt(0))); 8203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch StoreObjectFieldNoWriteBarrier( 8204c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch iterator, JSArrayIterator::kIteratedObjectMapOffset, array_map); 8205c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return iterator; 8206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 820862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsDetachedBuffer(Node* buffer) { 8209c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, HasInstanceType(buffer, JS_ARRAY_BUFFER_TYPE)); 8210c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8211c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* buffer_bit_field = LoadObjectField( 8212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); 821362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsSetWord32<JSArrayBuffer::WasNeutered>(buffer_bit_field); 8214c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 821662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochCodeStubArguments::CodeStubArguments(CodeStubAssembler* assembler, Node* argc, 821762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* fp, 8218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeStubAssembler::ParameterMode mode) 8219c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : assembler_(assembler), 822062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch argc_mode_(mode), 8221c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch argc_(argc), 8222c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch arguments_(nullptr), 822362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch fp_(fp != nullptr ? fp : assembler->LoadFramePointer()) { 822462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* offset = assembler->ElementOffsetFromIndex( 8225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch argc_, FAST_ELEMENTS, mode, 8226c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (StandardFrameConstants::kFixedSlotCountAboveFp - 1) * kPointerSize); 822762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch arguments_ = assembler_->IntPtrAdd(fp_, offset); 8228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8229c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 823062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubArguments::GetReceiver() const { 8231c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return assembler_->Load(MachineType::AnyTagged(), arguments_, 8232c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler_->IntPtrConstant(kPointerSize)); 8233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8234c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 823562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubArguments::AtIndexPtr( 823662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index, CodeStubAssembler::ParameterMode mode) const { 8237c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch typedef compiler::Node Node; 823862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* negated_index = assembler_->IntPtrOrSmiSub( 823962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch assembler_->IntPtrOrSmiConstant(0, mode), index, mode); 8240c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* offset = 8241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler_->ElementOffsetFromIndex(negated_index, FAST_ELEMENTS, mode, 0); 824262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return assembler_->IntPtrAdd(arguments_, offset); 8243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8244c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 824562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubArguments::AtIndex(Node* index, 824662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeStubAssembler::ParameterMode mode) const { 824762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(argc_mode_, mode); 824862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(assembler_, 824962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch assembler_->UintPtrOrSmiLessThan(index, GetLength(), mode)); 825062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return assembler_->Load(MachineType::AnyTagged(), AtIndexPtr(index, mode)); 825162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 825262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 825362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubArguments::AtIndex(int index) const { 8254c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return AtIndex(assembler_->IntPtrConstant(index)); 8255c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8256c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 825762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubArguments::ForEach( 825862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const CodeStubAssembler::VariableList& vars, 825962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const CodeStubArguments::ForEachBodyFunction& body, Node* first, Node* last, 826062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeStubAssembler::ParameterMode mode) { 8261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler_->Comment("CodeStubArguments::ForEach"); 8262c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (first == nullptr) { 8263c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch first = assembler_->IntPtrOrSmiConstant(0, mode); 8264c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 8265c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (last == nullptr) { 826662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(mode, argc_mode_); 8267c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch last = argc_; 8268c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 826962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* start = assembler_->IntPtrSub( 8270c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch arguments_, 8271c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler_->ElementOffsetFromIndex(first, FAST_ELEMENTS, mode)); 827262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* end = assembler_->IntPtrSub( 8273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch arguments_, 8274c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler_->ElementOffsetFromIndex(last, FAST_ELEMENTS, mode)); 827562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch assembler_->BuildFastLoop(vars, start, end, 827662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch [this, &body](Node* current) { 827762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* arg = assembler_->Load( 827862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::AnyTagged(), current); 827962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch body(arg); 828062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }, 828162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch -kPointerSize, CodeStubAssembler::INTPTR_PARAMETERS, 828262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeStubAssembler::IndexAdvanceMode::kPost); 8283c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8284c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 828562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubArguments::PopAndReturn(Node* value) { 8286c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch assembler_->PopAndReturn( 828762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch assembler_->IntPtrAdd(argc_, assembler_->IntPtrConstant(1)), value); 8288c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 829062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsFastElementsKind(Node* elements_kind) { 8291c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Uint32LessThanOrEqual(elements_kind, 8292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Int32Constant(LAST_FAST_ELEMENTS_KIND)); 8293c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8294c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 829562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsHoleyFastElementsKind(Node* elements_kind) { 8296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CSA_ASSERT(this, IsFastElementsKind(elements_kind)); 8297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8298c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); 8299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); 8300c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); 8301c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 8302c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check prototype chain if receiver does not have packed elements. 8303c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); 8304c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Word32Equal(holey_elements, Int32Constant(1)); 8305c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 8306c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 830762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsDebugActive() { 830862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* is_debug_active = Load( 830962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::Uint8(), 831062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); 831162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Word32NotEqual(is_debug_active, Int32Constant(0)); 831262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 831362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 831462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::IsPromiseHookEnabledOrDebugIsActive() { 831562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const promise_hook_or_debug_is_active = 831662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Load(MachineType::Uint8(), 831762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalConstant( 831862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalReference::promise_hook_or_debug_is_active_address( 831962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate()))); 832062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Word32NotEqual(promise_hook_or_debug_is_active, Int32Constant(0)); 832162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 832262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 832362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::AllocateFunctionWithMapAndContext(Node* map, 832462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* shared_info, 832562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* context) { 832662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const code = BitcastTaggedToWord( 832762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(shared_info, SharedFunctionInfo::kCodeOffset)); 832862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const code_entry = 832962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrAdd(code, IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); 833062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 833162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const fun = Allocate(JSFunction::kSize); 833262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(fun, map); 833362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldRoot(fun, JSObject::kPropertiesOffset, 833462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kEmptyFixedArrayRootIndex); 833562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldRoot(fun, JSObject::kElementsOffset, 833662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kEmptyFixedArrayRootIndex); 833762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldRoot(fun, JSFunction::kFeedbackVectorOffset, 833862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kUndefinedCellRootIndex); 833962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldRoot(fun, JSFunction::kPrototypeOrInitialMapOffset, 834062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kTheHoleValueRootIndex); 834162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(fun, JSFunction::kSharedFunctionInfoOffset, 834262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch shared_info); 834362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(fun, JSFunction::kContextOffset, context); 834462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(fun, JSFunction::kCodeEntryOffset, code_entry, 834562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::PointerRepresentation()); 834662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldRoot(fun, JSFunction::kNextFunctionLinkOffset, 834762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Heap::kUndefinedValueRootIndex); 834862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 834962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return fun; 835062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 835162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 835262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::AllocatePromiseReactionJobInfo( 835362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value, Node* tasks, Node* deferred_promise, Node* deferred_on_resolve, 835462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* deferred_on_reject, Node* context) { 835562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const result = Allocate(PromiseReactionJobInfo::kSize); 835662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreMapNoWriteBarrier(result, Heap::kPromiseReactionJobInfoMapRootIndex); 835762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kValueOffset, 835862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value); 835962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kTasksOffset, 836062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch tasks); 836162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier( 836262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result, PromiseReactionJobInfo::kDeferredPromiseOffset, deferred_promise); 836362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier( 836462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result, PromiseReactionJobInfo::kDeferredOnResolveOffset, 836562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch deferred_on_resolve); 836662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier( 836762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result, PromiseReactionJobInfo::kDeferredOnRejectOffset, 836862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch deferred_on_reject); 836962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kContextOffset, 837062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch context); 837162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return result; 837262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 837362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 837462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::MarkerIsFrameType(Node* marker_or_function, 837562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StackFrame::Type frame_type) { 837662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return WordEqual( 837762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch marker_or_function, 837862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); 837962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 838062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 838162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* CodeStubAssembler::MarkerIsNotFrameType(Node* marker_or_function, 838262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StackFrame::Type frame_type) { 838362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return WordNotEqual( 838462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch marker_or_function, 838562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch IntPtrConstant(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); 838662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 838762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 838862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::Print(const char* s) { 838962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#ifdef DEBUG 839062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch std::string formatted(s); 839162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch formatted += "\n"; 839262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<String> string = isolate()->factory()->NewStringFromAsciiChecked( 839362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch formatted.c_str(), TENURED); 839462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), HeapConstant(string)); 839562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif 839662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 839762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 839862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid CodeStubAssembler::Print(const char* prefix, Node* tagged_value) { 839962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#ifdef DEBUG 840062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (prefix != nullptr) { 840162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch std::string formatted(prefix); 840262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch formatted += ": "; 840362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<String> string = isolate()->factory()->NewStringFromAsciiChecked( 840462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch formatted.c_str(), TENURED); 840562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), 840662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HeapConstant(string)); 840762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 840862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); 840962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif 841062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 841162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 8412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace internal 8413bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace v8 8414