blob: f8fde15895ac12a2c8c737ab8e13172f86036788 [file] [log] [blame]
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "code-stubs.h"
31#include "hydrogen.h"
32#include "lithium.h"
33
34namespace v8 {
35namespace internal {
36
37
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000038static LChunk* OptimizeGraph(HGraph* graph) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +000039 DisallowHeapAllocation no_allocation;
40 DisallowHandleAllocation no_handles;
41 DisallowHandleDereference no_deref;
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000042
43 ASSERT(graph != NULL);
danno@chromium.org59400602013-08-13 17:09:37 +000044 BailoutReason bailout_reason = kNoReason;
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000045 if (!graph->Optimize(&bailout_reason)) {
danno@chromium.org59400602013-08-13 17:09:37 +000046 FATAL(GetBailoutReason(bailout_reason));
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000047 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000048 LChunk* chunk = LChunk::NewChunk(graph);
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000049 if (chunk == NULL) {
danno@chromium.org59400602013-08-13 17:09:37 +000050 FATAL(GetBailoutReason(graph->info()->bailout_reason()));
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000051 }
52 return chunk;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000053}
54
55
56class CodeStubGraphBuilderBase : public HGraphBuilder {
57 public:
58 CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub)
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000059 : HGraphBuilder(&info_),
60 arguments_length_(NULL),
61 info_(stub, isolate),
62 context_(NULL) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000063 descriptor_ = stub->GetInterfaceDescriptor(isolate);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000064 parameters_.Reset(new HParameter*[descriptor_->register_param_count_]);
65 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000066 virtual bool BuildGraph();
67
68 protected:
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000069 virtual HValue* BuildCodeStub() = 0;
70 HParameter* GetParameter(int parameter) {
71 ASSERT(parameter < descriptor_->register_param_count_);
72 return parameters_[parameter];
73 }
74 HValue* GetArgumentsLength() {
75 // This is initialized in BuildGraph()
76 ASSERT(arguments_length_ != NULL);
77 return arguments_length_;
78 }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000079 CompilationInfo* info() { return &info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000080 HydrogenCodeStub* stub() { return info_.code_stub(); }
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +000081 HContext* context() { return context_; }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000082 Isolate* isolate() { return info_.isolate(); }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000083
ulan@chromium.org57ff8812013-05-10 08:16:55 +000084 class ArrayContextChecker {
85 public:
86 ArrayContextChecker(HGraphBuilder* builder, HValue* constructor,
87 HValue* array_function)
88 : checker_(builder) {
89 checker_.If<HCompareObjectEqAndBranch, HValue*>(constructor,
90 array_function);
91 checker_.Then();
92 }
93
94 ~ArrayContextChecker() {
danno@chromium.org59400602013-08-13 17:09:37 +000095 checker_.ElseDeopt("Array constructor called from different context");
ulan@chromium.org57ff8812013-05-10 08:16:55 +000096 checker_.End();
97 }
98 private:
99 IfBuilder checker_;
100 };
101
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000102 enum ArgumentClass {
103 NONE,
104 SINGLE,
105 MULTIPLE
106 };
107
108 HValue* BuildArrayConstructor(ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000109 ContextCheckMode context_mode,
110 AllocationSiteOverrideMode override_mode,
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000111 ArgumentClass argument_class);
112 HValue* BuildInternalArrayConstructor(ElementsKind kind,
113 ArgumentClass argument_class);
114
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000115 void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context,
116 HValue* code_object);
117 void BuildInstallCode(HValue* js_function, HValue* shared_info);
118 void BuildInstallFromOptimizedCodeMap(HValue* js_function,
119 HValue* shared_info,
120 HValue* native_context);
121
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000122 private:
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000123 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
124 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
125 ElementsKind kind);
126
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000127 SmartArrayPointer<HParameter*> parameters_;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000128 HValue* arguments_length_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000129 CompilationInfoWithZone info_;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000130 CodeStubInterfaceDescriptor* descriptor_;
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000131 HContext* context_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000132};
133
134
135bool CodeStubGraphBuilderBase::BuildGraph() {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000136 // Update the static counter each time a new code stub is generated.
137 isolate()->counters()->code_stubs()->Increment();
138
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000139 if (FLAG_trace_hydrogen_stubs) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000140 const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000141 PrintF("-----------------------------------------------------------\n");
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000142 PrintF("Compiling stub %s using hydrogen\n", name);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000143 isolate()->GetHTracer()->TraceCompilation(&info_);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000144 }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000145
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000146 int param_count = descriptor_->register_param_count_;
147 HEnvironment* start_environment = graph()->start_environment();
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000148 HBasicBlock* next_block = CreateBasicBlock(start_environment);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000149 current_block()->Goto(next_block);
150 next_block->SetJoinId(BailoutId::StubEntry());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000151 set_current_block(next_block);
152
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000153 HConstant* undefined_constant =
154 Add<HConstant>(isolate()->factory()->undefined_value());
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000155 graph()->set_undefined_constant(undefined_constant);
156
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000157 for (int i = 0; i < param_count; ++i) {
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000158 HParameter* param =
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000159 Add<HParameter>(i, HParameter::REGISTER_PARAMETER);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000160 start_environment->Bind(i, param);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000161 parameters_[i] = param;
162 }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000163
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000164 HInstruction* stack_parameter_count;
165 if (descriptor_->stack_parameter_count_ != NULL) {
166 ASSERT(descriptor_->environment_length() == (param_count + 1));
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000167 stack_parameter_count = New<HParameter>(param_count,
168 HParameter::REGISTER_PARAMETER,
169 Representation::Integer32());
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000170 stack_parameter_count->set_type(HType::Smi());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000171 // It's essential to bind this value to the environment in case of deopt.
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000172 AddInstruction(stack_parameter_count);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000173 start_environment->Bind(param_count, stack_parameter_count);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000174 arguments_length_ = stack_parameter_count;
175 } else {
176 ASSERT(descriptor_->environment_length() == param_count);
177 stack_parameter_count = graph()->GetConstantMinus1();
178 arguments_length_ = graph()->GetConstant0();
179 }
180
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000181 context_ = New<HContext>();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000182 AddInstruction(context_);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000183 start_environment->BindContext(context_);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000184
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000185 Add<HSimulate>(BailoutId::StubEntry());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000186
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000187 NoObservableSideEffectsScope no_effects(this);
188
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000189 HValue* return_value = BuildCodeStub();
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000190
191 // We might have extra expressions to pop from the stack in addition to the
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000192 // arguments above.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000193 HInstruction* stack_pop_count = stack_parameter_count;
194 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000195 if (!stack_parameter_count->IsConstant() &&
196 descriptor_->hint_stack_parameter_count_ < 0) {
197 HInstruction* amount = graph()->GetConstant1();
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000198 stack_pop_count = Add<HAdd>(stack_parameter_count, amount);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000199 stack_pop_count->ChangeRepresentation(Representation::Integer32());
200 stack_pop_count->ClearFlag(HValue::kCanOverflow);
201 } else {
202 int count = descriptor_->hint_stack_parameter_count_;
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000203 stack_pop_count = Add<HConstant>(count);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000204 }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000205 }
206
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000207 if (current_block() != NULL) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000208 HReturn* hreturn_instruction = New<HReturn>(return_value,
209 stack_pop_count);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000210 current_block()->Finish(hreturn_instruction);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000211 set_current_block(NULL);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000212 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000213 return true;
214}
215
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000216
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000217template <class Stub>
218class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
219 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000220 explicit CodeStubGraphBuilder(Isolate* isolate, Stub* stub)
221 : CodeStubGraphBuilderBase(isolate, stub) {}
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000222
223 protected:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000224 virtual HValue* BuildCodeStub() {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000225 if (casted_stub()->IsUninitialized()) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000226 return BuildCodeUninitializedStub();
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000227 } else {
228 return BuildCodeInitializedStub();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000229 }
230 }
231
232 virtual HValue* BuildCodeInitializedStub() {
233 UNIMPLEMENTED();
234 return NULL;
235 }
236
237 virtual HValue* BuildCodeUninitializedStub() {
238 // Force a deopt that falls back to the runtime.
239 HValue* undefined = graph()->GetConstantUndefined();
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000240 IfBuilder builder(this);
241 builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined);
242 builder.Then();
danno@chromium.org59400602013-08-13 17:09:37 +0000243 builder.ElseDeopt("Forced deopt to runtime");
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000244 return undefined;
245 }
246
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000247 Stub* casted_stub() { return static_cast<Stub*>(stub()); }
248};
249
250
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000251Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode(Isolate* isolate) {
252 Factory* factory = isolate->factory();
253
254 // Generate the new code.
255 MacroAssembler masm(isolate, NULL, 256);
256
257 {
258 // Update the static counter each time a new code stub is generated.
259 isolate->counters()->code_stubs()->Increment();
260
261 // Nested stubs are not allowed for leaves.
262 AllowStubCallsScope allow_scope(&masm, false);
263
264 // Generate the code for the stub.
265 masm.set_generating_stub(true);
266 NoCurrentFrameScope scope(&masm);
267 GenerateLightweightMiss(&masm);
268 }
269
270 // Create the code object.
271 CodeDesc desc;
272 masm.GetCode(&desc);
273
274 // Copy the generated code into a heap object.
275 Code::Flags flags = Code::ComputeFlags(
276 GetCodeKind(),
277 GetICState(),
278 GetExtraICState(),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000279 GetStubType(),
280 GetStubFlags());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000281 Handle<Code> new_object = factory->NewCode(
282 desc, flags, masm.CodeObject(), NeedsImmovableCode());
283 return new_object;
284}
285
286
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000287template <class Stub>
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000288static Handle<Code> DoGenerateCode(Isolate* isolate, Stub* stub) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000289 CodeStub::Major major_key =
290 static_cast<HydrogenCodeStub*>(stub)->MajorKey();
291 CodeStubInterfaceDescriptor* descriptor =
292 isolate->code_stub_interface_descriptor(major_key);
293 if (descriptor->register_param_count_ < 0) {
294 stub->InitializeInterfaceDescriptor(isolate, descriptor);
295 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000296
297 // If we are uninitialized we can use a light-weight stub to enter
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000298 // the runtime that is significantly faster than using the standard
299 // stub-failure deopt mechanism.
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000300 if (stub->IsUninitialized() && descriptor->has_miss_handler()) {
301 ASSERT(descriptor->stack_parameter_count_ == NULL);
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000302 return stub->GenerateLightweightMissCode(isolate);
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000303 }
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000304 ElapsedTimer timer;
305 if (FLAG_profile_hydrogen_code_stub_compilation) {
306 timer.Start();
307 }
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000308 CodeStubGraphBuilder<Stub> builder(isolate, stub);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000309 LChunk* chunk = OptimizeGraph(builder.CreateGraph());
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000310 Handle<Code> code = chunk->Codegen();
311 if (FLAG_profile_hydrogen_code_stub_compilation) {
312 double ms = timer.Elapsed().InMillisecondsF();
313 PrintF("[Lazy compilation of %s took %0.3f ms]\n", *stub->GetName(), ms);
314 }
315 return code;
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000316}
317
318
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000319template <>
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000320HValue* CodeStubGraphBuilder<ToNumberStub>::BuildCodeStub() {
321 HValue* value = GetParameter(0);
322
323 // Check if the parameter is already a SMI or heap number.
324 IfBuilder if_number(this);
325 if_number.If<HIsSmiAndBranch>(value);
326 if_number.OrIf<HCompareMap>(value, isolate()->factory()->heap_number_map());
327 if_number.Then();
328
329 // Return the number.
330 Push(value);
331
332 if_number.Else();
333
334 // Convert the parameter to number using the builtin.
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000335 HValue* function = AddLoadJSBuiltin(Builtins::TO_NUMBER);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000336 Add<HPushArgument>(value);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000337 Push(Add<HInvokeFunction>(function, 1));
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000338
339 if_number.End();
340
341 return Pop();
342}
343
344
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000345Handle<Code> ToNumberStub::GenerateCode(Isolate* isolate) {
346 return DoGenerateCode(isolate, this);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000347}
348
349
350template <>
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +0000351HValue* CodeStubGraphBuilder<NumberToStringStub>::BuildCodeStub() {
352 info()->MarkAsSavesCallerDoubles();
353 HValue* number = GetParameter(NumberToStringStub::kNumber);
354 return BuildNumberToString(number);
355}
356
357
358Handle<Code> NumberToStringStub::GenerateCode(Isolate* isolate) {
359 return DoGenerateCode(isolate, this);
360}
361
362
363template <>
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000364HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000365 Factory* factory = isolate()->factory();
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000366 HValue* undefined = graph()->GetConstantUndefined();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000367 AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode();
368 FastCloneShallowArrayStub::Mode mode = casted_stub()->mode();
369 int length = casted_stub()->length();
370
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000371 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0),
372 GetParameter(1),
373 static_cast<HValue*>(NULL),
374 FAST_ELEMENTS);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000375 IfBuilder checker(this);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000376 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
377 undefined);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000378 checker.Then();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000379
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000380 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo();
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000381 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000382 HValue* push_value;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000383 if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) {
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +0000384 HValue* elements = AddLoadElements(boilerplate);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000385
386 IfBuilder if_fixed_cow(this);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000387 if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map());
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000388 if_fixed_cow.Then();
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000389 push_value = BuildCloneShallowArray(boilerplate,
390 allocation_site,
391 alloc_site_mode,
392 FAST_ELEMENTS,
393 0/*copy-on-write*/);
394 environment()->Push(push_value);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000395 if_fixed_cow.Else();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000396
397 IfBuilder if_fixed(this);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000398 if_fixed.If<HCompareMap>(elements, factory->fixed_array_map());
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000399 if_fixed.Then();
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000400 push_value = BuildCloneShallowArray(boilerplate,
401 allocation_site,
402 alloc_site_mode,
403 FAST_ELEMENTS,
404 length);
405 environment()->Push(push_value);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000406 if_fixed.Else();
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000407 push_value = BuildCloneShallowArray(boilerplate,
408 allocation_site,
409 alloc_site_mode,
410 FAST_DOUBLE_ELEMENTS,
411 length);
412 environment()->Push(push_value);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000413 } else {
414 ElementsKind elements_kind = casted_stub()->ComputeElementsKind();
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000415 push_value = BuildCloneShallowArray(boilerplate,
416 allocation_site,
417 alloc_site_mode,
418 elements_kind,
419 length);
420 environment()->Push(push_value);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000421 }
422
danno@chromium.org59400602013-08-13 17:09:37 +0000423 checker.ElseDeopt("Uninitialized boilerplate literals");
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000424 checker.End();
425
426 return environment()->Pop();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000427}
428
429
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000430Handle<Code> FastCloneShallowArrayStub::GenerateCode(Isolate* isolate) {
431 return DoGenerateCode(isolate, this);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000432}
433
434
435template <>
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000436HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000437 HValue* undefined = graph()->GetConstantUndefined();
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000438
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000439 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0),
440 GetParameter(1),
441 static_cast<HValue*>(NULL),
442 FAST_ELEMENTS);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000443
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000444 IfBuilder checker(this);
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000445 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000446 undefined);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000447 checker.And();
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000448
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000449 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo();
450 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access);
451
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000452 int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize;
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000453 int object_size = size;
454 if (FLAG_allocation_site_pretenuring) {
455 size += AllocationMemento::kSize;
456 }
457
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000458 HValue* boilerplate_map = Add<HLoadNamedField>(
459 boilerplate, HObjectAccess::ForMap());
460 HValue* boilerplate_size = Add<HLoadNamedField>(
461 boilerplate_map, HObjectAccess::ForMapInstanceSize());
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000462 HValue* size_in_words = Add<HConstant>(object_size >> kPointerSizeLog2);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000463 checker.If<HCompareNumericAndBranch>(boilerplate_size,
464 size_in_words, Token::EQ);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000465 checker.Then();
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000466
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000467 HValue* size_in_bytes = Add<HConstant>(size);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000468
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000469 HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(),
470 isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000471
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000472 for (int i = 0; i < object_size; i += kPointerSize) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000473 HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000474 Add<HStoreNamedField>(object, access,
475 Add<HLoadNamedField>(boilerplate, access));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000476 }
477
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000478 ASSERT(FLAG_allocation_site_pretenuring || (size == object_size));
479 if (FLAG_allocation_site_pretenuring) {
480 BuildCreateAllocationMemento(object, object_size, allocation_site);
481 }
482
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000483 environment()->Push(object);
danno@chromium.org59400602013-08-13 17:09:37 +0000484 checker.ElseDeopt("Uninitialized boilerplate in fast clone");
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000485 checker.End();
486
487 return environment()->Pop();
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000488}
489
490
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000491Handle<Code> FastCloneShallowObjectStub::GenerateCode(Isolate* isolate) {
492 return DoGenerateCode(isolate, this);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000493}
494
495
496template <>
danno@chromium.orgbee51992013-07-10 14:57:15 +0000497HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000498 HValue* size = Add<HConstant>(AllocationSite::kSize);
499 HInstruction* object = Add<HAllocate>(size, HType::JSObject(), TENURED,
500 JS_OBJECT_TYPE);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000501
502 // Store the map
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000503 Handle<Map> allocation_site_map = isolate()->factory()->allocation_site_map();
danno@chromium.orgbee51992013-07-10 14:57:15 +0000504 AddStoreMapConstant(object, allocation_site_map);
505
506 // Store the payload (smi elements kind)
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000507 HValue* initial_elements_kind = Add<HConstant>(GetInitialFastElementsKind());
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000508 Add<HStoreNamedField>(object,
509 HObjectAccess::ForAllocationSiteTransitionInfo(),
510 initial_elements_kind);
511
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +0000512 // Unlike literals, constructed arrays don't have nested sites
513 Add<HStoreNamedField>(object,
514 HObjectAccess::ForAllocationSiteNestedSite(),
515 graph()->GetConstant0());
516
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000517 // Store an empty fixed array for the code dependency.
518 HConstant* empty_fixed_array =
519 Add<HConstant>(isolate()->factory()->empty_fixed_array());
520 HStoreNamedField* store = Add<HStoreNamedField>(
521 object,
522 HObjectAccess::ForAllocationSiteDependentCode(),
523 empty_fixed_array);
524
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000525 // Link the object to the allocation site list
526 HValue* site_list = Add<HConstant>(
527 ExternalReference::allocation_sites_list_address(isolate()));
528 HValue* site = Add<HLoadNamedField>(site_list,
529 HObjectAccess::ForAllocationSiteList());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000530 store = Add<HStoreNamedField>(object,
531 HObjectAccess::ForAllocationSiteWeakNext(),
532 site);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000533 store->SkipWriteBarrier();
534 Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(),
535 object);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000536
537 // We use a hammer (SkipWriteBarrier()) to indicate that we know the input
538 // cell is really a Cell, and so no write barrier is needed.
539 // TODO(mvstanton): Add a debug_code check to verify the input cell is really
540 // a cell. (perhaps with a new instruction, HAssert).
541 HInstruction* cell = GetParameter(0);
542 HObjectAccess access = HObjectAccess::ForCellValue();
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000543 store = Add<HStoreNamedField>(cell, access, object);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000544 store->SkipWriteBarrier();
545 return cell;
546}
547
548
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000549Handle<Code> CreateAllocationSiteStub::GenerateCode(Isolate* isolate) {
550 return DoGenerateCode(isolate, this);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000551}
552
553
554template <>
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000555HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000556 HInstruction* load = BuildUncheckedMonomorphicElementAccess(
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000557 GetParameter(0), GetParameter(1), NULL,
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000558 casted_stub()->is_js_array(), casted_stub()->elements_kind(),
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000559 false, NEVER_RETURN_HOLE, STANDARD_STORE);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000560 return load;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000561}
562
563
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000564Handle<Code> KeyedLoadFastElementStub::GenerateCode(Isolate* isolate) {
565 return DoGenerateCode(isolate, this);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000566}
567
568
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000569template<>
570HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000571 Representation rep = casted_stub()->representation();
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000572 HObjectAccess access = casted_stub()->is_inobject() ?
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000573 HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) :
574 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep);
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +0000575 return AddInstruction(BuildLoadNamedField(GetParameter(0), access));
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000576}
577
578
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000579Handle<Code> LoadFieldStub::GenerateCode(Isolate* isolate) {
580 return DoGenerateCode(isolate, this);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000581}
582
583
584template<>
585HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000586 Representation rep = casted_stub()->representation();
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000587 HObjectAccess access = casted_stub()->is_inobject() ?
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000588 HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) :
589 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep);
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +0000590 return AddInstruction(BuildLoadNamedField(GetParameter(0), access));
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000591}
592
593
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000594Handle<Code> KeyedLoadFieldStub::GenerateCode(Isolate* isolate) {
595 return DoGenerateCode(isolate, this);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000596}
597
598
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000599template <>
600HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
601 BuildUncheckedMonomorphicElementAccess(
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000602 GetParameter(0), GetParameter(1), GetParameter(2),
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000603 casted_stub()->is_js_array(), casted_stub()->elements_kind(),
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000604 true, NEVER_RETURN_HOLE, casted_stub()->store_mode());
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000605
606 return GetParameter(2);
607}
608
609
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000610Handle<Code> KeyedStoreFastElementStub::GenerateCode(Isolate* isolate) {
611 return DoGenerateCode(isolate, this);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000612}
613
614
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000615template <>
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000616HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000617 info()->MarkAsSavesCallerDoubles();
618
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000619 BuildTransitionElementsKind(GetParameter(0),
620 GetParameter(1),
621 casted_stub()->from_kind(),
622 casted_stub()->to_kind(),
623 true);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000624
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000625 return GetParameter(0);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000626}
627
628
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000629Handle<Code> TransitionElementsKindStub::GenerateCode(Isolate* isolate) {
630 return DoGenerateCode(isolate, this);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000631}
632
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000633HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000634 ElementsKind kind,
635 ContextCheckMode context_mode,
636 AllocationSiteOverrideMode override_mode,
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000637 ArgumentClass argument_class) {
638 HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000639 if (context_mode == CONTEXT_CHECK_REQUIRED) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000640 HInstruction* array_function = BuildGetArrayFunction();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000641 ArrayContextChecker checker(this, constructor, array_function);
642 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000643
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000644 HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000645 // Walk through the property cell to the AllocationSite
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000646 HValue* alloc_site = Add<HLoadNamedField>(property_cell,
647 HObjectAccess::ForCellValue());
danno@chromium.orgbee51992013-07-10 14:57:15 +0000648 JSArrayBuilder array_builder(this, kind, alloc_site, constructor,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000649 override_mode);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000650 HValue* result = NULL;
651 switch (argument_class) {
652 case NONE:
653 result = array_builder.AllocateEmptyArray();
654 break;
655 case SINGLE:
656 result = BuildArraySingleArgumentConstructor(&array_builder);
657 break;
658 case MULTIPLE:
659 result = BuildArrayNArgumentsConstructor(&array_builder, kind);
660 break;
661 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000662
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000663 return result;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000664}
665
666
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000667HValue* CodeStubGraphBuilderBase::BuildInternalArrayConstructor(
668 ElementsKind kind, ArgumentClass argument_class) {
669 HValue* constructor = GetParameter(
670 InternalArrayConstructorStubBase::kConstructor);
671 JSArrayBuilder array_builder(this, kind, constructor);
672
673 HValue* result = NULL;
674 switch (argument_class) {
675 case NONE:
676 result = array_builder.AllocateEmptyArray();
677 break;
678 case SINGLE:
679 result = BuildArraySingleArgumentConstructor(&array_builder);
680 break;
681 case MULTIPLE:
682 result = BuildArrayNArgumentsConstructor(&array_builder, kind);
683 break;
684 }
685 return result;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000686}
687
688
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000689HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor(
690 JSArrayBuilder* array_builder) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000691 // Smi check and range check on the input arg.
692 HValue* constant_one = graph()->GetConstant1();
693 HValue* constant_zero = graph()->GetConstant0();
694
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000695 HInstruction* elements = Add<HArgumentsElements>(false);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000696 HInstruction* argument = AddInstruction(
697 new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero));
698
699 HConstant* max_alloc_length =
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000700 Add<HConstant>(JSObject::kInitialMaxFastElementArray);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000701 const int initial_capacity = JSArray::kPreallocatedArrayElements;
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000702 HConstant* initial_capacity_node = New<HConstant>(initial_capacity);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000703 AddInstruction(initial_capacity_node);
704
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000705 HInstruction* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000706 IfBuilder if_builder(this);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000707 if_builder.If<HCompareNumericAndBranch>(checked_arg, constant_zero,
708 Token::EQ);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000709 if_builder.Then();
710 Push(initial_capacity_node); // capacity
711 Push(constant_zero); // length
712 if_builder.Else();
713 Push(checked_arg); // capacity
714 Push(checked_arg); // length
715 if_builder.End();
716
717 // Figure out total size
718 HValue* length = Pop();
719 HValue* capacity = Pop();
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000720 return array_builder->AllocateArray(capacity, length, true);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000721}
722
723
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000724HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
725 JSArrayBuilder* array_builder, ElementsKind kind) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000726 // We need to fill with the hole if it's a smi array in the multi-argument
727 // case because we might have to bail out while copying arguments into
728 // the array because they aren't compatible with a smi array.
729 // If it's a double array, no problem, and if it's fast then no
730 // problem either because doubles are boxed.
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000731 HValue* length = GetArgumentsLength();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000732 bool fill_with_hole = IsFastSmiElementsKind(kind);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000733 HValue* new_object = array_builder->AllocateArray(length,
734 length,
735 fill_with_hole);
736 HValue* elements = array_builder->GetElementsLocation();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000737 ASSERT(elements != NULL);
738
739 // Now populate the elements correctly.
740 LoopBuilder builder(this,
741 context(),
742 LoopBuilder::kPostIncrement);
743 HValue* start = graph()->GetConstant0();
744 HValue* key = builder.BeginBody(start, length, Token::LT);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000745 HInstruction* argument_elements = Add<HArgumentsElements>(false);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000746 HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt(
747 argument_elements, length, key));
748
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000749 Add<HStoreKeyed>(elements, key, argument, kind);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000750 builder.EndBody();
751 return new_object;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000752}
753
754
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000755template <>
756HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
757 ElementsKind kind = casted_stub()->elements_kind();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000758 ContextCheckMode context_mode = casted_stub()->context_mode();
759 AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
760 return BuildArrayConstructor(kind, context_mode, override_mode, NONE);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000761}
762
763
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000764Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode(Isolate* isolate) {
765 return DoGenerateCode(isolate, this);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000766}
767
768
769template <>
770HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
771 BuildCodeStub() {
772 ElementsKind kind = casted_stub()->elements_kind();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000773 ContextCheckMode context_mode = casted_stub()->context_mode();
774 AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
775 return BuildArrayConstructor(kind, context_mode, override_mode, SINGLE);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000776}
777
778
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000779Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode(
780 Isolate* isolate) {
781 return DoGenerateCode(isolate, this);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000782}
783
784
785template <>
786HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
787 ElementsKind kind = casted_stub()->elements_kind();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000788 ContextCheckMode context_mode = casted_stub()->context_mode();
789 AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
790 return BuildArrayConstructor(kind, context_mode, override_mode, MULTIPLE);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000791}
792
793
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000794Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode(Isolate* isolate) {
795 return DoGenerateCode(isolate, this);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000796}
797
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000798
799template <>
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000800HValue* CodeStubGraphBuilder<InternalArrayNoArgumentConstructorStub>::
801 BuildCodeStub() {
802 ElementsKind kind = casted_stub()->elements_kind();
803 return BuildInternalArrayConstructor(kind, NONE);
804}
805
806
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000807Handle<Code> InternalArrayNoArgumentConstructorStub::GenerateCode(
808 Isolate* isolate) {
809 return DoGenerateCode(isolate, this);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000810}
811
812
813template <>
814HValue* CodeStubGraphBuilder<InternalArraySingleArgumentConstructorStub>::
815 BuildCodeStub() {
816 ElementsKind kind = casted_stub()->elements_kind();
817 return BuildInternalArrayConstructor(kind, SINGLE);
818}
819
820
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000821Handle<Code> InternalArraySingleArgumentConstructorStub::GenerateCode(
822 Isolate* isolate) {
823 return DoGenerateCode(isolate, this);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000824}
825
826
827template <>
828HValue* CodeStubGraphBuilder<InternalArrayNArgumentsConstructorStub>::
829 BuildCodeStub() {
830 ElementsKind kind = casted_stub()->elements_kind();
831 return BuildInternalArrayConstructor(kind, MULTIPLE);
832}
833
834
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000835Handle<Code> InternalArrayNArgumentsConstructorStub::GenerateCode(
836 Isolate* isolate) {
837 return DoGenerateCode(isolate, this);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000838}
839
840
841template <>
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000842HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
danno@chromium.org41728482013-06-12 22:31:22 +0000843 Isolate* isolate = graph()->isolate();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000844 CompareNilICStub* stub = casted_stub();
845 HIfContinuation continuation;
danno@chromium.org41728482013-06-12 22:31:22 +0000846 Handle<Map> sentinel_map(isolate->heap()->meta_map());
danno@chromium.org169691d2013-07-15 08:01:13 +0000847 Handle<Type> type = stub->GetType(isolate, sentinel_map);
danno@chromium.org41728482013-06-12 22:31:22 +0000848 BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000849 IfBuilder if_nil(this, &continuation);
850 if_nil.Then();
851 if (continuation.IsFalseReachable()) {
852 if_nil.Else();
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000853 if_nil.Return(graph()->GetConstant0());
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000854 }
855 if_nil.End();
856 return continuation.IsTrueReachable()
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000857 ? graph()->GetConstant1()
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000858 : graph()->GetConstantUndefined();
859}
860
861
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000862Handle<Code> CompareNilICStub::GenerateCode(Isolate* isolate) {
863 return DoGenerateCode(isolate, this);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000864}
865
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000866
867template <>
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000868HValue* CodeStubGraphBuilder<BinaryOpStub>::BuildCodeInitializedStub() {
869 BinaryOpStub* stub = casted_stub();
870 HValue* left = GetParameter(0);
871 HValue* right = GetParameter(1);
872
873 Handle<Type> left_type = stub->GetLeftType(isolate());
874 Handle<Type> right_type = stub->GetRightType(isolate());
875 Handle<Type> result_type = stub->GetResultType(isolate());
876
877 ASSERT(!left_type->Is(Type::None()) && !right_type->Is(Type::None()) &&
878 (stub->HasSideEffects(isolate()) || !result_type->Is(Type::None())));
879
880 HValue* result = NULL;
881 if (stub->operation() == Token::ADD &&
882 (left_type->Maybe(Type::String()) || right_type->Maybe(Type::String())) &&
883 !left_type->Is(Type::String()) && !right_type->Is(Type::String())) {
884 // For the generic add stub a fast case for String add is performance
885 // critical.
886 if (left_type->Maybe(Type::String())) {
887 IfBuilder left_string(this);
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +0000888 left_string.If<HIsStringAndBranch>(left);
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000889 left_string.Then();
890 Push(Add<HStringAdd>(left, right, STRING_ADD_CHECK_RIGHT));
891 left_string.Else();
892 Push(AddInstruction(BuildBinaryOperation(stub->operation(),
893 left, right, left_type, right_type, result_type,
894 stub->fixed_right_arg(), true)));
895 left_string.End();
896 result = Pop();
897 } else {
898 IfBuilder right_string(this);
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +0000899 right_string.If<HIsStringAndBranch>(right);
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000900 right_string.Then();
901 Push(Add<HStringAdd>(left, right, STRING_ADD_CHECK_LEFT));
902 right_string.Else();
903 Push(AddInstruction(BuildBinaryOperation(stub->operation(),
904 left, right, left_type, right_type, result_type,
905 stub->fixed_right_arg(), true)));
906 right_string.End();
907 result = Pop();
908 }
909 } else {
910 result = AddInstruction(BuildBinaryOperation(stub->operation(),
911 left, right, left_type, right_type, result_type,
912 stub->fixed_right_arg(), true));
913 }
914
915 // If we encounter a generic argument, the number conversion is
916 // observable, thus we cannot afford to bail out after the fact.
917 if (!stub->HasSideEffects(isolate())) {
918 if (result_type->Is(Type::Smi())) {
919 if (stub->operation() == Token::SHR) {
920 // TODO(olivf) Replace this by a SmiTagU Instruction.
921 // 0x40000000: this number would convert to negative when interpreting
922 // the register as signed value;
923 IfBuilder if_of(this);
924 if_of.IfNot<HCompareNumericAndBranch>(result,
925 Add<HConstant>(static_cast<int>(SmiValuesAre32Bits()
926 ? 0x80000000 : 0x40000000)), Token::EQ_STRICT);
927 if_of.Then();
928 if_of.ElseDeopt("UInt->Smi oveflow");
929 if_of.End();
930 }
931 }
932 result = EnforceNumberType(result, result_type);
933 }
934
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000935 // Reuse the double box of one of the operands if we are allowed to (i.e.
936 // chained binops).
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000937 if (stub->CanReuseDoubleBox()) {
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000938 HValue* operand = (stub->mode() == OVERWRITE_LEFT) ? left : right;
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000939 IfBuilder if_heap_number(this);
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000940 if_heap_number.IfNot<HIsSmiAndBranch>(operand);
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000941 if_heap_number.Then();
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000942 Add<HStoreNamedField>(operand, HObjectAccess::ForHeapNumberValue(), result);
943 Push(operand);
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000944 if_heap_number.Else();
945 Push(result);
946 if_heap_number.End();
947 result = Pop();
948 }
949
950 return result;
951}
952
953
954Handle<Code> BinaryOpStub::GenerateCode(Isolate* isolate) {
955 return DoGenerateCode(isolate, this);
956}
957
958
959template <>
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000960HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
961 ToBooleanStub* stub = casted_stub();
962
963 IfBuilder if_true(this);
964 if_true.If<HBranch>(GetParameter(0), stub->GetTypes());
965 if_true.Then();
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000966 if_true.Return(graph()->GetConstant1());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000967 if_true.Else();
968 if_true.End();
969 return graph()->GetConstant0();
970}
971
972
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000973Handle<Code> ToBooleanStub::GenerateCode(Isolate* isolate) {
974 return DoGenerateCode(isolate, this);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000975}
976
977
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000978template <>
979HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
980 StoreGlobalStub* stub = casted_stub();
981 Handle<Object> hole(isolate()->heap()->the_hole_value(), isolate());
982 Handle<Object> placeholer_value(Smi::FromInt(0), isolate());
983 Handle<PropertyCell> placeholder_cell =
984 isolate()->factory()->NewPropertyCell(placeholer_value);
985
986 HParameter* receiver = GetParameter(0);
987 HParameter* value = GetParameter(2);
988
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000989 // Check that the map of the global has not changed: use a placeholder map
990 // that will be replaced later with the global object's map.
991 Handle<Map> placeholder_map = isolate()->factory()->meta_map();
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000992 Add<HCheckMaps>(receiver, placeholder_map, top_info());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000993
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000994 HValue* cell = Add<HConstant>(placeholder_cell);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000995 HObjectAccess access(HObjectAccess::ForCellPayload(isolate()));
996 HValue* cell_contents = Add<HLoadNamedField>(cell, access);
997
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000998 if (stub->is_constant()) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000999 IfBuilder builder(this);
1000 builder.If<HCompareObjectEqAndBranch>(cell_contents, value);
1001 builder.Then();
danno@chromium.org59400602013-08-13 17:09:37 +00001002 builder.ElseDeopt("Unexpected cell contents in constant global store");
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001003 builder.End();
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001004 } else {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001005 // Load the payload of the global parameter cell. A hole indicates that the
1006 // property has been deleted and that the store must be handled by the
1007 // runtime.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001008 IfBuilder builder(this);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001009 HValue* hole_value = Add<HConstant>(hole);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001010 builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value);
1011 builder.Then();
danno@chromium.org59400602013-08-13 17:09:37 +00001012 builder.Deopt("Unexpected cell contents in global store");
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001013 builder.Else();
1014 Add<HStoreNamedField>(cell, access, value);
1015 builder.End();
1016 }
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001017
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001018 return value;
1019}
1020
1021
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001022Handle<Code> StoreGlobalStub::GenerateCode(Isolate* isolate) {
1023 return DoGenerateCode(isolate, this);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001024}
1025
1026
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001027template<>
1028HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() {
1029 HValue* value = GetParameter(0);
1030 HValue* map = GetParameter(1);
1031 HValue* key = GetParameter(2);
1032 HValue* object = GetParameter(3);
1033
1034 if (FLAG_trace_elements_transitions) {
1035 // Tracing elements transitions is the job of the runtime.
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00001036 Add<HDeoptimize>("Tracing elements transitions", Deoptimizer::EAGER);
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001037 } else {
1038 info()->MarkAsSavesCallerDoubles();
1039
1040 BuildTransitionElementsKind(object, map,
1041 casted_stub()->from_kind(),
1042 casted_stub()->to_kind(),
1043 casted_stub()->is_jsarray());
1044
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001045 BuildUncheckedMonomorphicElementAccess(object, key, value,
1046 casted_stub()->is_jsarray(),
1047 casted_stub()->to_kind(),
1048 true, ALLOW_RETURN_HOLE,
1049 casted_stub()->store_mode());
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001050 }
1051
1052 return value;
1053}
1054
1055
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001056Handle<Code> ElementsTransitionAndStoreStub::GenerateCode(Isolate* isolate) {
1057 return DoGenerateCode(isolate, this);
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001058}
1059
1060
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001061void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(
1062 HValue* js_function,
1063 HValue* native_context,
1064 HValue* code_object) {
1065 Counters* counters = isolate()->counters();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001066 AddIncrementCounter(counters->fast_new_closure_install_optimized());
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001067
1068 // TODO(fschneider): Idea: store proper code pointers in the optimized code
1069 // map and either unmangle them on marking or do nothing as the whole map is
1070 // discarded on major GC anyway.
1071 Add<HStoreCodeEntry>(js_function, code_object);
1072
1073 // Now link a function into a list of optimized functions.
1074 HValue* optimized_functions_list = Add<HLoadNamedField>(native_context,
1075 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST));
1076 Add<HStoreNamedField>(js_function,
1077 HObjectAccess::ForNextFunctionLinkPointer(),
1078 optimized_functions_list);
1079
1080 // This store is the only one that should have a write barrier.
1081 Add<HStoreNamedField>(native_context,
1082 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST),
1083 js_function);
1084}
1085
1086
1087void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function,
1088 HValue* shared_info) {
1089 Add<HStoreNamedField>(js_function,
1090 HObjectAccess::ForNextFunctionLinkPointer(),
1091 graph()->GetConstantUndefined());
1092 HValue* code_object = Add<HLoadNamedField>(shared_info,
1093 HObjectAccess::ForCodeOffset());
1094 Add<HStoreCodeEntry>(js_function, code_object);
1095}
1096
1097
1098void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
1099 HValue* js_function,
1100 HValue* shared_info,
1101 HValue* native_context) {
1102 Counters* counters = isolate()->counters();
1103 IfBuilder is_optimized(this);
1104 HInstruction* optimized_map = Add<HLoadNamedField>(shared_info,
1105 HObjectAccess::ForOptimizedCodeMap());
1106 HValue* null_constant = Add<HConstant>(0);
1107 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant);
1108 is_optimized.Then();
1109 {
1110 BuildInstallCode(js_function, shared_info);
1111 }
1112 is_optimized.Else();
1113 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001114 AddIncrementCounter(counters->fast_new_closure_try_optimized());
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001115 // optimized_map points to fixed array of 3-element entries
1116 // (native context, optimized code, literals).
1117 // Map must never be empty, so check the first elements.
1118 Label install_optimized;
1119 HValue* first_context_slot = Add<HLoadNamedField>(optimized_map,
1120 HObjectAccess::ForFirstContextSlot());
1121 IfBuilder already_in(this);
1122 already_in.If<HCompareObjectEqAndBranch>(native_context,
1123 first_context_slot);
1124 already_in.Then();
1125 {
1126 HValue* code_object = Add<HLoadNamedField>(optimized_map,
1127 HObjectAccess::ForFirstCodeSlot());
1128 BuildInstallOptimizedCode(js_function, native_context, code_object);
1129 }
1130 already_in.Else();
1131 {
1132 HValue* shared_function_entry_length =
1133 Add<HConstant>(SharedFunctionInfo::kEntryLength);
1134 LoopBuilder loop_builder(this,
1135 context(),
1136 LoopBuilder::kPostDecrement,
1137 shared_function_entry_length);
1138 HValue* array_length = Add<HLoadNamedField>(optimized_map,
1139 HObjectAccess::ForFixedArrayLength());
1140 HValue* key = loop_builder.BeginBody(array_length,
1141 graph()->GetConstant0(),
1142 Token::GT);
1143 {
1144 // Iterate through the rest of map backwards.
1145 // Do not double check first entry.
1146 HValue* second_entry_index =
1147 Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex);
1148 IfBuilder restore_check(this);
1149 restore_check.If<HCompareNumericAndBranch>(key, second_entry_index,
1150 Token::EQ);
1151 restore_check.Then();
1152 {
1153 // Store the unoptimized code
1154 BuildInstallCode(js_function, shared_info);
1155 loop_builder.Break();
1156 }
1157 restore_check.Else();
1158 {
1159 HValue* keyed_minus = AddInstruction(HSub::New(zone(), context(), key,
1160 shared_function_entry_length));
1161 HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map,
1162 keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1163 IfBuilder done_check(this);
1164 done_check.If<HCompareObjectEqAndBranch>(native_context,
1165 keyed_lookup);
1166 done_check.Then();
1167 {
1168 // Hit: fetch the optimized code.
1169 HValue* keyed_plus = AddInstruction(HAdd::New(zone(), context(),
1170 keyed_minus, graph()->GetConstant1()));
1171 HValue* code_object = Add<HLoadKeyed>(optimized_map,
1172 keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1173 BuildInstallOptimizedCode(js_function, native_context, code_object);
1174
1175 // Fall out of the loop
1176 loop_builder.Break();
1177 }
1178 done_check.Else();
1179 done_check.End();
1180 }
1181 restore_check.End();
1182 }
1183 loop_builder.EndBody();
1184 }
1185 already_in.End();
1186 }
1187 is_optimized.End();
1188}
1189
1190
1191template<>
1192HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
1193 Counters* counters = isolate()->counters();
1194 Factory* factory = isolate()->factory();
1195 HInstruction* empty_fixed_array =
1196 Add<HConstant>(factory->empty_fixed_array());
1197 HValue* shared_info = GetParameter(0);
1198
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001199 AddIncrementCounter(counters->fast_new_closure_total());
1200
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001201 // Create a new closure from the given function info in new space
1202 HValue* size = Add<HConstant>(JSFunction::kSize);
1203 HInstruction* js_function = Add<HAllocate>(size, HType::JSObject(),
1204 NOT_TENURED, JS_FUNCTION_TYPE);
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001205
1206 int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(),
1207 casted_stub()->is_generator());
1208
1209 // Compute the function map in the current native context and set that
1210 // as the map of the allocated object.
1211 HInstruction* native_context = BuildGetNativeContext();
1212 HInstruction* map_slot_value = Add<HLoadNamedField>(native_context,
1213 HObjectAccess::ForContextSlot(map_index));
1214 Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value);
1215
1216 // Initialize the rest of the function.
1217 Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(),
1218 empty_fixed_array);
1219 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(),
1220 empty_fixed_array);
1221 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(),
1222 empty_fixed_array);
1223 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(),
1224 graph()->GetConstantHole());
1225 Add<HStoreNamedField>(js_function,
1226 HObjectAccess::ForSharedFunctionInfoPointer(),
1227 shared_info);
1228 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(),
1229 shared_info);
1230 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(),
1231 context());
1232
1233 // Initialize the code pointer in the function to be the one
1234 // found in the shared function info object.
1235 // But first check if there is an optimized version for our context.
1236 if (FLAG_cache_optimized_code) {
1237 BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context);
1238 } else {
1239 BuildInstallCode(js_function, shared_info);
1240 }
1241
1242 return js_function;
1243}
1244
1245
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001246Handle<Code> FastNewClosureStub::GenerateCode(Isolate* isolate) {
1247 return DoGenerateCode(isolate, this);
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001248}
1249
1250
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001251} } // namespace v8::internal