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, &not_ok);
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&not_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)), &not_aligned,
756bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           &aligned);
757bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
758bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Bind(&not_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({&current_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, &current_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             &copy_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(&copy_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         &not_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(&not_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           &not_oddball);
3908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3909f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    var_result.Bind(LoadObjectField(value, Oddball::kToStringOffset));
3910f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Goto(&end);
3911f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3912f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Bind(&not_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), &not_smi);
4017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  var_result.Bind(input);
4018f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Goto(&end);
4019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
4020f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Bind(&not_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), &not_heap_number);
4025f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
4026f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    var_result.Bind(input);
4027f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Goto(&end);
4028f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
4029f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Bind(&not_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, &not_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(&not_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)), &not_private);
463762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* flags = SmiToWord32(LoadObjectField(name, Symbol::kFlagsOffset));
463862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const int kPrivateMask = 1 << Symbol::kPrivateBit;
463962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(IsSetWord32(flags, kPrivateMask), &not_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(&not_private);
464462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&not_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] = {&current_js_object, &current_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