1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/code-stubs.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <memory>
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bailout-reason.h"
10f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/code-factory.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/hydrogen.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/lithium.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/field-index.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/ic.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic LChunk* OptimizeGraph(HGraph* graph) {
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_allocation;
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHandleAllocation no_handles;
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHandleDereference no_deref;
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(graph != NULL);
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BailoutReason bailout_reason = kNoReason;
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!graph->Optimize(&bailout_reason)) {
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FATAL(GetBailoutReason(bailout_reason));
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LChunk* chunk = LChunk::NewChunk(graph);
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (chunk == NULL) {
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FATAL(GetBailoutReason(graph->info()->bailout_reason()));
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return chunk;
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeStubGraphBuilderBase : public HGraphBuilder {
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
40109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  explicit CodeStubGraphBuilderBase(CompilationInfo* info, CodeStub* code_stub)
41f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      : HGraphBuilder(info, code_stub->GetCallInterfaceDescriptor(), false),
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        arguments_length_(NULL),
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        info_(info),
44109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        code_stub_(code_stub),
45109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        descriptor_(code_stub),
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context_(NULL) {
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int parameter_count = GetParameterCount();
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    parameters_.reset(new HParameter*[parameter_count]);
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual bool BuildGraph();
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual HValue* BuildCodeStub() = 0;
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int GetParameterCount() const { return descriptor_.GetParameterCount(); }
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int GetRegisterParameterCount() const {
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return descriptor_.GetRegisterParameterCount();
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HParameter* GetParameter(int parameter) {
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(parameter < GetParameterCount());
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return parameters_[parameter];
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Representation GetParameterRepresentation(int parameter) {
63f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return RepresentationFromMachineType(
64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        descriptor_.GetParameterType(parameter));
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsParameterCountRegister(int index) const {
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return descriptor_.GetRegisterParameter(index)
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        .is(descriptor_.stack_parameter_count());
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* GetArgumentsLength() {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is initialized in BuildGraph()
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(arguments_length_ != NULL);
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return arguments_length_;
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CompilationInfo* info() { return info_; }
76109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CodeStub* stub() { return code_stub_; }
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HContext* context() { return context_; }
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Isolate* isolate() { return info_->isolate(); }
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index);
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index,
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            Representation representation,
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            bool transition_to_field);
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* BuildPushElement(HValue* object, HValue* argc,
863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           HValue* argument_elements, ElementsKind kind);
873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* BuildToString(HValue* input, bool convert);
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* BuildToPrimitive(HValue* input, HValue* input_map);
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::unique_ptr<HParameter* []> parameters_;
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* arguments_length_;
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CompilationInfo* info_;
95109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CodeStub* code_stub_;
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeStubDescriptor descriptor_;
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HContext* context_;
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CodeStubGraphBuilderBase::BuildGraph() {
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update the static counter each time a new code stub is generated.
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->code_stubs()->Increment();
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trace_hydrogen_stubs) {
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const char* name = CodeStub::MajorName(stub()->MajorKey());
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("-----------------------------------------------------------\n");
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("Compiling stub %s using hydrogen\n", name);
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    isolate()->GetHTracer()->TraceCompilation(info());
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int param_count = GetParameterCount();
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int register_param_count = GetRegisterParameterCount();
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HEnvironment* start_environment = graph()->start_environment();
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HBasicBlock* next_block = CreateBasicBlock(start_environment);
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Goto(next_block);
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  next_block->SetJoinId(BailoutId::StubEntry());
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_current_block(next_block);
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool runtime_stack_params = descriptor_.stack_parameter_count().is_valid();
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HInstruction* stack_parameter_count = NULL;
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < param_count; ++i) {
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Representation r = GetParameterRepresentation(i);
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    HParameter* param;
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (i >= register_param_count) {
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      param = Add<HParameter>(i - register_param_count,
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              HParameter::STACK_PARAMETER, r);
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      param = Add<HParameter>(i, HParameter::REGISTER_PARAMETER, r);
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    start_environment->Bind(i, param);
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    parameters_[i] = param;
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (i < register_param_count && IsParameterCountRegister(i)) {
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      param->set_type(HType::Smi());
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_parameter_count = param;
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      arguments_length_ = stack_parameter_count;
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!runtime_stack_params || arguments_length_ != NULL);
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!runtime_stack_params) {
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    stack_parameter_count =
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Add<HConstant>(param_count - register_param_count - 1);
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // graph()->GetConstantMinus1();
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arguments_length_ = graph()->GetConstant0();
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context_ = Add<HContext>();
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  start_environment->BindContext(context_);
150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  start_environment->Bind(param_count, context_);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Add<HSimulate>(BailoutId::StubEntry());
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NoObservableSideEffectsScope no_effects(this);
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* return_value = BuildCodeStub();
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We might have extra expressions to pop from the stack in addition to the
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // arguments above.
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HInstruction* stack_pop_count = stack_parameter_count;
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (descriptor_.function_mode() == JS_FUNCTION_STUB_MODE) {
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!stack_parameter_count->IsConstant() &&
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        descriptor_.hint_stack_parameter_count() < 0) {
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HInstruction* constant_one = graph()->GetConstant1();
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_pop_count = AddUncasted<HAdd>(stack_parameter_count, constant_one);
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_pop_count->ClearFlag(HValue::kCanOverflow);
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(mvstanton): verify that stack_parameter_count+1 really fits in a
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // smi.
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int count = descriptor_.hint_stack_parameter_count();
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_pop_count = Add<HConstant>(count);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (current_block() != NULL) {
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HReturn* hreturn_instruction = New<HReturn>(return_value,
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                stack_pop_count);
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FinishCurrentBlock(hreturn_instruction);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <class Stub>
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  explicit CodeStubGraphBuilder(CompilationInfo* info, CodeStub* stub)
188109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      : CodeStubGraphBuilderBase(info, stub) {}
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  typedef typename Stub::Descriptor Descriptor;
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual HValue* BuildCodeStub() {
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (casted_stub()->IsUninitialized()) {
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return BuildCodeUninitializedStub();
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return BuildCodeInitializedStub();
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual HValue* BuildCodeInitializedStub() {
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNIMPLEMENTED();
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NULL;
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual HValue* BuildCodeUninitializedStub() {
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Force a deopt that falls back to the runtime.
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HValue* undefined = graph()->GetConstantUndefined();
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    IfBuilder builder(this);
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined);
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    builder.Then();
212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    builder.ElseDeopt(DeoptimizeReason::kForcedDeoptToRuntime);
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return undefined;
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Stub* casted_stub() { return static_cast<Stub*>(stub()); }
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> HydrogenCodeStub::GenerateLightweightMissCode(
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference miss) {
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate the new code.
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MacroAssembler masm(isolate(), NULL, 256, CodeObjectRequired::kYes);
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Update the static counter each time a new code stub is generated.
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate()->counters()->code_stubs()->Increment();
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Generate the code for the stub.
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm.set_generating_stub(true);
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // TODO(yangguo): remove this once we can serialize IC stubs.
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    masm.enable_serializer();
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NoCurrentFrameScope scope(&masm);
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GenerateLightweightMiss(&masm, miss);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create the code object.
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy the generated code into a heap object.
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> new_object = factory->NewCode(
245109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      desc, GetCodeFlags(), masm.CodeObject(), NeedsImmovableCode());
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_object;
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochHandle<Code> HydrogenCodeStub::GenerateRuntimeTailCall(
250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    CodeStubDescriptor* descriptor) {
251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const char* name = CodeStub::MajorName(MajorKey());
252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(isolate()->allocator(), ZONE_NAME);
253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CallInterfaceDescriptor interface_descriptor(GetCallInterfaceDescriptor());
254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CodeStubAssembler assembler(isolate(), &zone, interface_descriptor,
255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                              GetCodeFlags(), name);
256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int total_params = interface_descriptor.GetStackParameterCount() +
257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                     interface_descriptor.GetRegisterParameterCount();
258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (total_params) {
259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case 0:
260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      assembler.TailCallRuntime(descriptor->miss_handler_id(),
261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(0));
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case 1:
264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      assembler.TailCallRuntime(descriptor->miss_handler_id(),
265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(1), assembler.Parameter(0));
266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case 2:
268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      assembler.TailCallRuntime(descriptor->miss_handler_id(),
269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(2), assembler.Parameter(0),
270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(1));
271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case 3:
273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      assembler.TailCallRuntime(descriptor->miss_handler_id(),
274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(3), assembler.Parameter(0),
275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(1), assembler.Parameter(2));
276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case 4:
278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      assembler.TailCallRuntime(descriptor->miss_handler_id(),
279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(4), assembler.Parameter(0),
280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(1), assembler.Parameter(2),
281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                assembler.Parameter(3));
282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default:
284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      UNIMPLEMENTED();
285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return assembler.GenerateCode();
288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <class Stub>
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Handle<Code> DoGenerateCode(Stub* stub) {
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = stub->isolate();
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeStubDescriptor descriptor(stub);
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (FLAG_minimal && descriptor.has_miss_handler()) {
296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return stub->GenerateRuntimeTailCall(&descriptor);
297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we are uninitialized we can use a light-weight stub to enter
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the runtime that is significantly faster than using the standard
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stub-failure deopt mechanism.
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (stub->IsUninitialized() && descriptor.has_miss_handler()) {
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!descriptor.stack_parameter_count().is_valid());
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return stub->GenerateLightweightMissCode(descriptor.miss_handler());
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::ElapsedTimer timer;
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_profile_hydrogen_code_stub_compilation) {
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    timer.Start();
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(isolate->allocator(), ZONE_NAME);
311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  CompilationInfo info(CStrVector(CodeStub::MajorName(stub->MajorKey())),
312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                       isolate, &zone, stub->GetCodeFlags());
313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Parameter count is number of stack parameters.
314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int parameter_count = descriptor.GetStackParameterCount();
315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (descriptor.function_mode() == NOT_JS_FUNCTION_STUB_MODE) {
316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    parameter_count--;
317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  info.set_parameter_count(parameter_count);
319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CodeStubGraphBuilder<Stub> builder(&info, stub);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LChunk* chunk = OptimizeGraph(builder.CreateGraph());
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = chunk->Codegen();
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_profile_hydrogen_code_stub_compilation) {
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    os << "[Lazy compilation of " << stub << " took "
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       << timer.Elapsed().InMillisecondsF() << " ms]" << std::endl;
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return code;
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object, HValue* argc,
3323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                   HValue* argument_elements,
3333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                   ElementsKind kind) {
3343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Precheck whether all elements fit into the array.
3353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (!IsFastObjectElementsKind(kind)) {
3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
3373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* start = graph()->GetConstant0();
3383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* key = builder.BeginBody(start, argc, Token::LT);
3393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    {
3403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      HInstruction* argument =
3413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          Add<HAccessArgumentsAt>(argument_elements, argc, key);
3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      IfBuilder can_store(this);
3433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      can_store.IfNot<HIsSmiAndBranch>(argument);
3443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (IsFastDoubleElementsKind(kind)) {
3453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        can_store.And();
3463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        can_store.IfNot<HCompareMap>(argument,
3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                     isolate()->factory()->heap_number_map());
3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      can_store.ThenDeopt(DeoptimizeReason::kFastPathFailed);
3503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      can_store.End();
3513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
3523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    builder.EndBody();
3533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* length = Add<HLoadNamedField>(object, nullptr,
3563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        HObjectAccess::ForArrayLength(kind));
3573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* new_length = AddUncasted<HAdd>(length, argc);
3583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* max_key = AddUncasted<HSub>(new_length, graph()->GetConstant1());
3593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* elements = Add<HLoadNamedField>(object, nullptr,
3613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                          HObjectAccess::ForElementsPointer());
3623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  elements = BuildCheckForCapacityGrow(object, elements, kind, length, max_key,
3633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                       true, STORE);
3643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
3663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* start = graph()->GetConstant0();
3673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* key = builder.BeginBody(start, argc, Token::LT);
3683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key);
3703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* index = AddUncasted<HAdd>(key, length);
3713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    AddElementAccess(elements, index, argument, object, nullptr, kind, STORE);
3723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  builder.EndBody();
3743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return new_length;
3753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
3763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochtemplate <>
3783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() {
3793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // TODO(verwaest): Fix deoptimizer messages.
3803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* argc = GetArgumentsLength();
381f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
3833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
3843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                 graph()->GetConstantMinus1());
3853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  BuildCheckHeapObject(object);
3863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
3873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY);
3883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Disallow pushing onto prototypes. It might be the JSArray prototype.
3903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Disallow pushing onto non-extensible objects.
3913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
3923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* bit_field2 =
3933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
3943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* mask =
3953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Add<HConstant>(static_cast<int>(Map::IsPrototypeMapBits::kMask) |
3963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       (1 << Map::kIsExtensible));
3973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask);
3983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    IfBuilder check(this);
3993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    check.If<HCompareNumericAndBranch>(
4003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE);
401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    check.ThenDeopt(DeoptimizeReason::kFastPathFailed);
4023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    check.End();
4033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
4043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Disallow pushing onto arrays in dictionary named property mode. We need to
4063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // figure out whether the length property is still writable.
4073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
4083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* bit_field3 =
4093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
4103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask));
4113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
4123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    IfBuilder check(this);
4133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    check.ThenDeopt(DeoptimizeReason::kFastPathFailed);
4153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    check.End();
4163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
4173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Check whether the length property is writable. The length property is the
4193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // only default named property on arrays. It's nonconfigurable, hence is
4203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // guaranteed to stay the first property.
4213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
4223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* descriptors =
4233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors());
4243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* details = Add<HLoadKeyed>(
4253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        descriptors, Add<HConstant>(DescriptorArray::ToDetailsIndex(0)),
4263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        nullptr, nullptr, FAST_SMI_ELEMENTS);
4273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* mask =
4283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Add<HConstant>(READ_ONLY << PropertyDetails::AttributesField::kShift);
4293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask);
4303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    IfBuilder readonly(this);
4313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    readonly.ThenDeopt(DeoptimizeReason::kFastPathFailed);
4333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    readonly.End();
4343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
4353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* null = Add<HLoadRoot>(Heap::kNullValueRootIndex);
4373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* empty = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
4383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  environment()->Push(map);
4393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  LoopBuilder check_prototypes(this);
4403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  check_prototypes.BeginBody(1);
4413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
4423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* parent_map = environment()->Pop();
4433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr,
4443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                             HObjectAccess::ForPrototype());
4453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    IfBuilder is_null(this);
4473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    is_null.If<HCompareObjectEqAndBranch>(prototype, null);
4483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    is_null.Then();
4493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    check_prototypes.Break();
4503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    is_null.End();
4513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* prototype_map =
4533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap());
4543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* instance_type = Add<HLoadNamedField>(
4553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        prototype_map, nullptr, HObjectAccess::ForMapInstanceType());
4563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    IfBuilder check_instance_type(this);
4573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    check_instance_type.If<HCompareNumericAndBranch>(
4583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER),
4593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Token::LTE);
460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    check_instance_type.ThenDeopt(DeoptimizeReason::kFastPathFailed);
4613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    check_instance_type.End();
4623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* elements = Add<HLoadNamedField>(
4643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        prototype, nullptr, HObjectAccess::ForElementsPointer());
4653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    IfBuilder no_elements(this);
4663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty);
467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    no_elements.ThenDeopt(DeoptimizeReason::kFastPathFailed);
4683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    no_elements.End();
4693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    environment()->Push(prototype_map);
4713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
4723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  check_prototypes.EndBody();
4733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* bit_field2 =
4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2);
4773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Below we only check the upper bound of the relevant ranges to include both
4793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // holey and non-holey versions. We check them in order smi, object, double
4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // since smi < object < double.
4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS < FAST_HOLEY_SMI_ELEMENTS);
4823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS < FAST_HOLEY_ELEMENTS);
4833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(FAST_ELEMENTS < FAST_HOLEY_ELEMENTS);
4843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS);
4853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS);
4863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  IfBuilder has_smi_elements(this);
4873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  has_smi_elements.If<HCompareNumericAndBranch>(
4883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE);
4893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  has_smi_elements.Then();
4903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
4913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    HValue* new_length = BuildPushElement(object, argc, argument_elements,
4923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                          FAST_HOLEY_SMI_ELEMENTS);
4933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    environment()->Push(new_length);
4943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
4953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  has_smi_elements.Else();
4963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  {
4973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    IfBuilder has_object_elements(this);
4983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    has_object_elements.If<HCompareNumericAndBranch>(
4993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE);
5003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    has_object_elements.Then();
5013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    {
5023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      HValue* new_length = BuildPushElement(object, argc, argument_elements,
5033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                            FAST_HOLEY_ELEMENTS);
5043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      environment()->Push(new_length);
5053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
5063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    has_object_elements.Else();
5073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    {
5083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      IfBuilder has_double_elements(this);
5093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      has_double_elements.If<HCompareNumericAndBranch>(
5103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE);
5113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      has_double_elements.Then();
5123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      {
5133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        HValue* new_length = BuildPushElement(object, argc, argument_elements,
5143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                              FAST_HOLEY_DOUBLE_ELEMENTS);
5153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        environment()->Push(new_length);
5163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      has_double_elements.ElseDeopt(DeoptimizeReason::kFastPathFailed);
5183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      has_double_elements.End();
5193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
5203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    has_object_elements.End();
5213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
5223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  has_smi_elements.End();
5233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
5243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return environment()->Pop();
5253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
5263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
5273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHandle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); }
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <>
53013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochHValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() {
53113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // TODO(verwaest): Fix deoptimizer messages.
53213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* argc = GetArgumentsLength();
53313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
53413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                 graph()->GetConstantMinus1());
53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  BuildCheckHeapObject(object);
53713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
53813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION);
53913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
54013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Disallow binding of slow-mode functions. We need to figure out whether the
54113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // length and name property are in the original state.
54213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* bit_field3 =
54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
54513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask));
54613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
54713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    IfBuilder check(this);
54813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    check.ThenDeopt(DeoptimizeReason::kFastPathFailed);
55013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    check.End();
55113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
55213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
55313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Check whether the length and name properties are still present as
55413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // AccessorInfo objects. In that case, their value can be recomputed even if
55513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // the actual value on the object changes.
55613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
55713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* descriptors =
55813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors());
55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
56013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* descriptors_length = Add<HLoadNamedField>(
56113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        descriptors, nullptr, HObjectAccess::ForFixedArrayLength());
56213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    IfBuilder range(this);
56313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    range.If<HCompareNumericAndBranch>(descriptors_length,
56413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                       graph()->GetConstant1(), Token::LTE);
565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    range.ThenDeopt(DeoptimizeReason::kFastPathFailed);
56613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    range.End();
56713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
56813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Verify .length.
56913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    const int length_index = JSFunction::kLengthDescriptorIndex;
57013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* maybe_length = Add<HLoadKeyed>(
57113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)),
57213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        nullptr, nullptr, FAST_ELEMENTS);
57313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Unique<Name> length_string = Unique<Name>::CreateUninitialized(
57413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        isolate()->factory()->length_string());
57513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Add<HCheckValue>(maybe_length, length_string, false);
57613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
57713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* maybe_length_accessor = Add<HLoadKeyed>(
57813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        descriptors,
57913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Add<HConstant>(DescriptorArray::ToValueIndex(length_index)), nullptr,
58013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        nullptr, FAST_ELEMENTS);
58113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    BuildCheckHeapObject(maybe_length_accessor);
58213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Add<HCheckMaps>(maybe_length_accessor,
58313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                    isolate()->factory()->accessor_info_map());
58413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
58513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Verify .name.
58613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    const int name_index = JSFunction::kNameDescriptorIndex;
58713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* maybe_name = Add<HLoadKeyed>(
58813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(name_index)),
58913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        nullptr, nullptr, FAST_ELEMENTS);
59013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Unique<Name> name_string =
59113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Unique<Name>::CreateUninitialized(isolate()->factory()->name_string());
59213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Add<HCheckValue>(maybe_name, name_string, false);
59313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
59413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* maybe_name_accessor = Add<HLoadKeyed>(
59513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        descriptors, Add<HConstant>(DescriptorArray::ToValueIndex(name_index)),
59613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        nullptr, nullptr, FAST_ELEMENTS);
59713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    BuildCheckHeapObject(maybe_name_accessor);
59813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Add<HCheckMaps>(maybe_name_accessor,
59913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                    isolate()->factory()->accessor_info_map());
60013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
60113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
60213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Choose the right bound function map based on whether the target is
60313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // constructable.
60413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
60513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* bit_field =
60613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
60713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* mask = Add<HConstant>(static_cast<int>(1 << Map::kIsConstructor));
60813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask);
60913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
61013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* native_context = BuildGetNativeContext();
61113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    IfBuilder is_constructor(this);
61213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    is_constructor.If<HCompareNumericAndBranch>(bits, mask, Token::EQ);
61313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    is_constructor.Then();
61413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    {
61513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      HValue* map = Add<HLoadNamedField>(
61613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          native_context, nullptr,
61713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          HObjectAccess::ForContextSlot(
61813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch              Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
61913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      environment()->Push(map);
62013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
62113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    is_constructor.Else();
62213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    {
62313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      HValue* map = Add<HLoadNamedField>(
62413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          native_context, nullptr,
62513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          HObjectAccess::ForContextSlot(
62613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch              Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
62713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      environment()->Push(map);
62813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
62913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    is_constructor.End();
63013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
63113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* bound_function_map = environment()->Pop();
63213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
63313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Verify that __proto__ matches that of a the target bound function.
63413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
63513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* prototype =
63613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype());
63713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* expected_prototype = Add<HLoadNamedField>(
63813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        bound_function_map, nullptr, HObjectAccess::ForPrototype());
63913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    IfBuilder equal_prototype(this);
64013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype,
64113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                     expected_prototype);
642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    equal_prototype.ThenDeopt(DeoptimizeReason::kFastPathFailed);
64313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    equal_prototype.End();
64413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
64613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Allocate the arguments array.
64713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  IfBuilder empty_args(this);
64813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(),
64913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                          Token::LTE);
65013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  empty_args.Then();
65113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); }
65213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  empty_args.Else();
65313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
65413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* elements_length = AddUncasted<HSub>(argc, graph()->GetConstant1());
65513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* elements =
65613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        BuildAllocateAndInitializeArray(FAST_ELEMENTS, elements_length);
65713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
65813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
65913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* start = graph()->GetConstant1();
66013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HValue* key = builder.BeginBody(start, argc, Token::LT);
66113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    {
66213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key);
66313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      HValue* index = AddUncasted<HSub>(key, graph()->GetConstant1());
66413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      AddElementAccess(elements, index, argument, elements, nullptr,
66513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                       FAST_ELEMENTS, STORE);
66613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
66713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    builder.EndBody();
66813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    environment()->Push(elements);
66913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
67013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  empty_args.End();
67113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* elements = environment()->Pop();
67213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
67313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Find the 'this' to bind.
67413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  IfBuilder no_receiver(this);
67513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  no_receiver.If<HCompareNumericAndBranch>(argc, graph()->GetConstant0(),
67613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                           Token::EQ);
67713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  no_receiver.Then();
67813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  { environment()->Push(Add<HLoadRoot>(Heap::kUndefinedValueRootIndex)); }
67913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  no_receiver.Else();
68013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
68113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    environment()->Push(Add<HAccessArgumentsAt>(argument_elements, argc,
68213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                graph()->GetConstant0()));
68313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
68413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  no_receiver.End();
68513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* receiver = environment()->Pop();
68613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
68713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Allocate the resulting bound function.
68813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* size = Add<HConstant>(JSBoundFunction::kSize);
68913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* bound_function =
69013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Add<HAllocate>(size, HType::JSObject(), NOT_TENURED,
69113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                     JS_BOUND_FUNCTION_TYPE, graph()->GetConstant0());
69213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HStoreNamedField>(bound_function, HObjectAccess::ForMap(),
69313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                        bound_function_map);
69413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
69513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HStoreNamedField>(bound_function, HObjectAccess::ForPropertiesPointer(),
69613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                        empty_fixed_array);
69713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HStoreNamedField>(bound_function, HObjectAccess::ForElementsPointer(),
69813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                        empty_fixed_array);
69913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundTargetFunction(),
70013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                        object);
70113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
70213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundThis(),
70313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                        receiver);
70413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundArguments(),
70513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                        elements);
70613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
70713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return bound_function;
70813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
70913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
71013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochHandle<Code> FastFunctionBindStub::GenerateCode() {
71113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return DoGenerateCode(this);
71213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
71313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
71413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <>
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() {
716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadKeyedHoleMode hole_mode = casted_stub()->convert_hole_to_undefined()
717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    ? CONVERT_HOLE_TO_UNDEFINED
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    : NEVER_RETURN_HOLE;
719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HInstruction* load = BuildUncheckedMonomorphicElementAccess(
721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      GetParameter(Descriptor::kReceiver), GetParameter(Descriptor::kName),
722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NULL, casted_stub()->is_js_array(), casted_stub()->elements_kind(), LOAD,
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      hole_mode, STANDARD_STORE);
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return load;
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadFastElementStub::GenerateCode() {
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return DoGenerateCode(this);
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHLoadNamedField* CodeStubGraphBuilderBase::BuildLoadNamedField(
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HValue* object, FieldIndex index) {
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Representation representation = index.is_double()
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? Representation::Double()
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Representation::Tagged();
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = index.offset();
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess access = index.is_inobject()
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? HObjectAccess::ForObservableJSObjectOffset(offset, representation)
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : HObjectAccess::ForBackingStoreOffset(offset, representation);
742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (index.is_double() &&
743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      (!FLAG_unbox_double_fields || !index.is_inobject())) {
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the heap number.
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object = Add<HLoadNamedField>(
746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        object, nullptr, access.WithRepresentation(Representation::Tagged()));
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the double value from it.
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    access = HObjectAccess::ForHeapNumberValue();
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return Add<HLoadNamedField>(object, nullptr, access);
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<>
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return BuildLoadNamedField(GetParameter(Descriptor::kReceiver),
757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             casted_stub()->index());
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadFieldStub::GenerateCode() {
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return DoGenerateCode(this);
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <>
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() {
768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* map = AddLoadMap(GetParameter(Descriptor::kReceiver), NULL);
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess descriptors_access = HObjectAccess::ForObservableJSObjectOffset(
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Map::kDescriptorsOffset, Representation::Tagged());
771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HValue* descriptors = Add<HLoadNamedField>(map, nullptr, descriptors_access);
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset(
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DescriptorArray::GetValueOffset(casted_stub()->constant_index()));
774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return Add<HLoadNamedField>(descriptors, nullptr, value_access);
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); }
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeStubGraphBuilderBase::BuildStoreNamedField(
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HValue* object, HValue* value, FieldIndex index,
783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Representation representation, bool transition_to_field) {
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!index.is_double() || representation.IsDouble());
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = index.offset();
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess access =
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      index.is_inobject()
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ? HObjectAccess::ForObservableJSObjectOffset(offset, representation)
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          : HObjectAccess::ForBackingStoreOffset(offset, representation);
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (representation.IsDouble()) {
792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!FLAG_unbox_double_fields || !index.is_inobject()) {
793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      HObjectAccess heap_number_access =
794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          access.WithRepresentation(Representation::Tagged());
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (transition_to_field) {
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // The store requires a mutable HeapNumber to be allocated.
797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        NoObservableSideEffectsScope no_side_effects(this);
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // TODO(hpayer): Allocation site pretenuring support.
801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        HInstruction* heap_number =
802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
803bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AddStoreMapConstant(heap_number,
805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            isolate()->factory()->mutable_heap_number_map());
806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              value);
808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Store the new mutable heap number into the object.
809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        access = heap_number_access;
810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        value = heap_number;
811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Load the heap number.
813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        object = Add<HLoadNamedField>(object, nullptr, heap_number_access);
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Store the double value into it.
815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        access = HObjectAccess::ForHeapNumberValue();
816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (representation.IsHeapObject()) {
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BuildCheckHeapObject(value);
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Add<HStoreNamedField>(object, access, value, INITIALIZING_STORE);
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <>
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
82813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ElementsKind const from_kind = casted_stub()->from_kind();
82913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ElementsKind const to_kind = casted_stub()->to_kind();
830f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* const object = GetParameter(Descriptor::kObject);
831f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* const map = GetParameter(Descriptor::kMap);
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
83313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // The {object} is known to be a JSObject (otherwise it wouldn't have elements
83413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // anyways).
83513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  object->set_type(HType::JSObject());
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
83713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  info()->MarkAsSavesCallerDoubles();
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
83913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK_IMPLIES(IsFastHoleyElementsKind(from_kind),
84013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                 IsFastHoleyElementsKind(to_kind));
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
84213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
84313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Add<HTrapAllocationMemento>(object);
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
84613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
84713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    HInstruction* elements = AddLoadElements(object);
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
84913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    IfBuilder if_objecthaselements(this);
85013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if_objecthaselements.IfNot<HCompareObjectEqAndBranch>(
85113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        elements, Add<HConstant>(isolate()->factory()->empty_fixed_array()));
85213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if_objecthaselements.Then();
85313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    {
85413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // Determine the elements capacity.
85513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      HInstruction* elements_length = AddLoadFixedArrayLength(elements);
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
85713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // Determine the effective (array) length.
85813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      IfBuilder if_objectisarray(this);
85913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if_objectisarray.If<HHasInstanceTypeAndBranch>(object, JS_ARRAY_TYPE);
86013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if_objectisarray.Then();
86113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      {
86213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        // The {object} is a JSArray, load the special "length" property.
86313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Push(Add<HLoadNamedField>(object, nullptr,
86413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                  HObjectAccess::ForArrayLength(from_kind)));
86513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
86613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if_objectisarray.Else();
86713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      {
86813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        // The {object} is some other JSObject.
86913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Push(elements_length);
87013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
87113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if_objectisarray.End();
87213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      HValue* length = Pop();
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
87413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      BuildGrowElementsCapacity(object, elements, from_kind, to_kind, length,
87513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                elements_length);
87613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
87713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if_objecthaselements.End();
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
88013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
88213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return object;
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
88613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochHandle<Code> TransitionElementsKindStub::GenerateCode() {
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return DoGenerateCode(this);
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <>
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() {
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BinaryOpICState state = casted_stub()->state();
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* left = GetParameter(Descriptor::kLeft);
895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* right = GetParameter(Descriptor::kRight);
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
897f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  AstType* left_type = state.GetLeftType();
898f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  AstType* right_type = state.GetRightType();
899f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  AstType* result_type = state.GetResultType();
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
901f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(!left_type->Is(AstType::None()) && !right_type->Is(AstType::None()) &&
902f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch         (state.HasSideEffects() || !result_type->Is(AstType::None())));
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* result = NULL;
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HAllocationMode allocation_mode(NOT_TENURED);
906f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (state.op() == Token::ADD && (left_type->Maybe(AstType::String()) ||
907f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                   right_type->Maybe(AstType::String())) &&
908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      !left_type->Is(AstType::String()) && !right_type->Is(AstType::String())) {
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For the generic add stub a fast case for string addition is performance
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // critical.
911f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (left_type->Maybe(AstType::String())) {
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      IfBuilder if_leftisstring(this);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_leftisstring.If<HIsStringAndBranch>(left);
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_leftisstring.Then();
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
916f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Push(BuildBinaryOperation(state.op(), left, right, AstType::String(),
917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  right_type, result_type,
918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  state.fixed_right_arg(), allocation_mode));
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_leftisstring.Else();
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        Push(BuildBinaryOperation(state.op(), left, right, left_type,
923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  right_type, result_type,
924109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  state.fixed_right_arg(), allocation_mode));
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_leftisstring.End();
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result = Pop();
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      IfBuilder if_rightisstring(this);
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_rightisstring.If<HIsStringAndBranch>(right);
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_rightisstring.Then();
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Push(BuildBinaryOperation(state.op(), left, right, left_type,
934f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                  AstType::String(), result_type,
935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  state.fixed_right_arg(), allocation_mode));
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_rightisstring.Else();
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
939109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        Push(BuildBinaryOperation(state.op(), left, right, left_type,
940109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  right_type, result_type,
941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  state.fixed_right_arg(), allocation_mode));
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if_rightisstring.End();
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result = Pop();
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    result = BuildBinaryOperation(state.op(), left, right, left_type,
948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  right_type, result_type,
949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                  state.fixed_right_arg(), allocation_mode);
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we encounter a generic argument, the number conversion is
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // observable, thus we cannot afford to bail out after the fact.
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!state.HasSideEffects()) {
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result = EnforceNumberType(result, result_type);
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> BinaryOpICStub::GenerateCode() {
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return DoGenerateCode(this);
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <>
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<BinaryOpWithAllocationSiteStub>::BuildCodeStub() {
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BinaryOpICState state = casted_stub()->state();
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
971f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* allocation_site = GetParameter(Descriptor::kAllocationSite);
972f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* left = GetParameter(Descriptor::kLeft);
973f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* right = GetParameter(Descriptor::kRight);
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  AstType* left_type = state.GetLeftType();
976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  AstType* right_type = state.GetRightType();
977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  AstType* result_type = state.GetResultType();
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HAllocationMode allocation_mode(allocation_site);
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return BuildBinaryOperation(state.op(), left, right, left_type, right_type,
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              result_type, state.fixed_right_arg(),
982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                              allocation_mode);
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> BinaryOpWithAllocationSiteStub::GenerateCode() {
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return DoGenerateCode(this);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHValue* CodeStubGraphBuilderBase::BuildToString(HValue* input, bool convert) {
992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!convert) return BuildCheckString(input);
993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IfBuilder if_inputissmi(this);
994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* inputissmi = if_inputissmi.If<HIsSmiAndBranch>(input);
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputissmi.Then();
996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Convert the input smi to a string.
998f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Push(BuildNumberToString(input, AstType::SignedSmall()));
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputissmi.Else();
1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    HValue* input_map =
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Add<HLoadNamedField>(input, inputissmi, HObjectAccess::ForMap());
1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    HValue* input_instance_type = Add<HLoadNamedField>(
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        input_map, inputissmi, HObjectAccess::ForMapInstanceType());
1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    IfBuilder if_inputisstring(this);
1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if_inputisstring.If<HCompareNumericAndBranch>(
1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        input_instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE), Token::LT);
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if_inputisstring.Then();
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    {
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // The input is already a string.
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(input);
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if_inputisstring.Else();
1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    {
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Convert to primitive first (if necessary), see
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // ES6 section 12.7.3 The Addition operator.
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      IfBuilder if_inputisprimitive(this);
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if_inputisprimitive.If<HCompareNumericAndBranch>(
1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          input_instance_type, Add<HConstant>(LAST_PRIMITIVE_TYPE), Token::LTE);
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if_inputisprimitive.Then();
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      {
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // The input is already a primitive.
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Push(input);
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if_inputisprimitive.Else();
1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      {
1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Convert the input to a primitive.
1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Push(BuildToPrimitive(input, input_map));
1031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if_inputisprimitive.End();
1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Convert the primitive to a string value.
1034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      HValue* values[] = {Pop()};
1035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Callable toString = CodeFactory::ToString(isolate());
1036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Push(AddUncasted<HCallWithDescriptor>(Add<HConstant>(toString.code()), 0,
1037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                            toString.descriptor(),
1038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                            ArrayVector(values)));
1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if_inputisstring.End();
1041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputissmi.End();
1043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Pop();
1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHValue* CodeStubGraphBuilderBase::BuildToPrimitive(HValue* input,
1048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                   HValue* input_map) {
1049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Get the native context of the caller.
1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* native_context = BuildGetNativeContext();
1051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Determine the initial map of the %ObjectPrototype%.
1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* object_function_prototype_map =
1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Add<HLoadNamedField>(native_context, nullptr,
1055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           HObjectAccess::ForContextSlot(
1056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               Context::OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX));
1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Determine the initial map of the %StringPrototype%.
1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* string_function_prototype_map =
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Add<HLoadNamedField>(native_context, nullptr,
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           HObjectAccess::ForContextSlot(
1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Determine the initial map of the String function.
1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* string_function = Add<HLoadNamedField>(
1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      native_context, nullptr,
1067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX));
1068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* string_function_initial_map = Add<HLoadNamedField>(
1069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      string_function, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
1070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Determine the map of the [[Prototype]] of {input}.
1072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* input_prototype =
1073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Add<HLoadNamedField>(input_map, nullptr, HObjectAccess::ForPrototype());
1074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HValue* input_prototype_map =
1075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Add<HLoadNamedField>(input_prototype, nullptr, HObjectAccess::ForMap());
1076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // For string wrappers (JSValue instances with [[StringData]] internal
1078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // fields), we can shortcirciut the ToPrimitive if
1079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
1080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  (a) the {input} map matches the initial map of the String function,
1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  (b) the {input} [[Prototype]] is the unmodified %StringPrototype% (i.e.
1082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //      no one monkey-patched toString, @@toPrimitive or valueOf), and
1083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  (c) the %ObjectPrototype% (i.e. the [[Prototype]] of the
1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //      %StringPrototype%) is also unmodified, that is no one sneaked a
1085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //      @@toPrimitive into the %ObjectPrototype%.
1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If all these assumptions hold, we can just take the [[StringData]] value
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and return it.
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(bmeurer): This just repairs a regression introduced by removing the
1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // weird (and broken) intrinsic %_IsStringWrapperSafeForDefaultValue, which
1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // was intendend to something similar to this, although less efficient and
1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // wrong in the presence of @@toPrimitive. Long-term we might want to move
1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // into the direction of having a ToPrimitiveStub that can do common cases
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // while staying in JavaScript land (i.e. not going to C++).
1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IfBuilder if_inputisstringwrapper(this);
1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.If<HCompareObjectEqAndBranch>(
1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      input_map, string_function_initial_map);
1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.And();
1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.If<HCompareObjectEqAndBranch>(
1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      input_prototype_map, string_function_prototype_map);
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.And();
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.If<HCompareObjectEqAndBranch>(
1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Add<HLoadNamedField>(Add<HLoadNamedField>(input_prototype_map, nullptr,
1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                HObjectAccess::ForPrototype()),
1105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           nullptr, HObjectAccess::ForMap()),
1106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      object_function_prototype_map);
1107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.Then();
1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(BuildLoadNamedField(
1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        input, FieldIndex::ForInObjectOffset(JSValue::kValueOffset)));
1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.Else();
1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(bmeurer): Add support for fast ToPrimitive conversion using
1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // a dedicated ToPrimitiveStub.
1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Add<HPushArguments>(input);
1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToPrimitive), 1));
1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_inputisstringwrapper.End();
1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Pop();
1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <>
11243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHValue* CodeStubGraphBuilder<ToBooleanICStub>::BuildCodeInitializedStub() {
11253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  ToBooleanICStub* stub = casted_stub();
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IfBuilder if_true(this);
1127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if_true.If<HBranch>(GetParameter(Descriptor::kArgument), stub->hints());
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if_true.Then();
1129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if_true.Return(graph()->GetConstantTrue());
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if_true.Else();
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if_true.End();
1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return graph()->GetConstantFalse();
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHandle<Code> ToBooleanICStub::GenerateCode() { return DoGenerateCode(this); }
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <>
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadDictionaryElementStub>::BuildCodeStub() {
1139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* receiver = GetParameter(Descriptor::kReceiver);
1140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HValue* key = GetParameter(Descriptor::kName);
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Add<HCheckSmi>(key);
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* elements = AddLoadElements(receiver);
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* hash = BuildElementIndexHash(key);
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash);
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadDictionaryElementStub::GenerateCode() {
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return DoGenerateCode(this);
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
1157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
1158