blob: 895569d41357ca34acea2c232dc406044a8cd64d [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/code-stubs.h"
6
7#include <sstream>
Steve Blocka7e24c12009-10-30 11:49:00 +00008
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/bootstrapper.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/cpu-profiler.h"
11#include "src/factory.h"
12#include "src/gdb-jit.h"
13#include "src/ic/handler-compiler.h"
14#include "src/ic/ic.h"
15#include "src/macro-assembler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000016
17namespace v8 {
18namespace internal {
19
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020
21CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
22 : call_descriptor_(stub->GetCallInterfaceDescriptor()),
23 stack_parameter_count_(no_reg),
24 hint_stack_parameter_count_(-1),
25 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
26 deoptimization_handler_(NULL),
27 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
28 miss_handler_(),
29 has_miss_handler_(false) {
30 stub->InitializeDescriptor(this);
31}
32
33
34CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
35 : stack_parameter_count_(no_reg),
36 hint_stack_parameter_count_(-1),
37 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
38 deoptimization_handler_(NULL),
39 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
40 miss_handler_(),
41 has_miss_handler_(false) {
42 CodeStub::InitializeDescriptor(isolate, stub_key, this);
43}
44
45
46void CodeStubDescriptor::Initialize(Address deoptimization_handler,
47 int hint_stack_parameter_count,
48 StubFunctionMode function_mode) {
49 deoptimization_handler_ = deoptimization_handler;
50 hint_stack_parameter_count_ = hint_stack_parameter_count;
51 function_mode_ = function_mode;
52}
53
54
55void CodeStubDescriptor::Initialize(Register stack_parameter_count,
56 Address deoptimization_handler,
57 int hint_stack_parameter_count,
58 StubFunctionMode function_mode,
59 HandlerArgumentsMode handler_mode) {
60 Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
61 stack_parameter_count_ = stack_parameter_count;
62 handler_arguments_mode_ = handler_mode;
63}
64
65
Leon Clarkee46be812010-01-19 14:06:41 +000066bool CodeStub::FindCodeInCache(Code** code_out) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
68 int index = stubs->FindEntry(GetKey());
Ben Murdochc7cc0282012-03-05 14:35:55 +000069 if (index != UnseededNumberDictionary::kNotFound) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 *code_out = Code::cast(stubs->ValueAt(index));
Leon Clarkee46be812010-01-19 14:06:41 +000071 return true;
Steve Blockd0582a62009-12-15 09:54:21 +000072 }
Leon Clarkee46be812010-01-19 14:06:41 +000073 return false;
74}
Steve Blockd0582a62009-12-15 09:54:21 +000075
Leon Clarkee46be812010-01-19 14:06:41 +000076
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077void CodeStub::RecordCodeGeneration(Handle<Code> code) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040078 std::ostringstream os;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 os << *this;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080 PROFILE(isolate(),
81 CodeCreateEvent(Logger::STUB_TAG, *code, os.str().c_str()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 Counters* counters = isolate()->counters();
Steve Block44f0eee2011-05-26 01:26:41 +010083 counters->total_stubs_code_size()->Increment(code->instruction_size());
Leon Clarkee46be812010-01-19 14:06:41 +000084}
85
86
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087Code::Kind CodeStub::GetCodeKind() const {
Steve Block6ded16b2010-05-10 14:33:55 +010088 return Code::STUB;
89}
90
91
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
93 Handle<Code> ic = GetCode();
94 ic = isolate()->factory()->CopyCode(ic);
95 ic->FindAndReplace(pattern);
96 RecordCodeGeneration(ic);
97 return ic;
98}
99
100
101Handle<Code> PlatformCodeStub::GenerateCode() {
102 Factory* factory = isolate()->factory();
103
104 // Generate the new code.
105 MacroAssembler masm(isolate(), NULL, 256);
106
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 {
108 // Update the static counter each time a new code stub is generated.
109 isolate()->counters()->code_stubs()->Increment();
110
111 // Generate the code for the stub.
112 masm.set_generating_stub(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400113 // TODO(yangguo): remove this once we can serialize IC stubs.
114 masm.enable_serializer();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 NoCurrentFrameScope scope(&masm);
116 Generate(&masm);
117 }
118
119 // Create the code object.
120 CodeDesc desc;
121 masm.GetCode(&desc);
122
123 // Copy the generated code into a heap object.
124 Code::Flags flags = Code::ComputeFlags(
125 GetCodeKind(),
126 GetICState(),
127 GetExtraICState(),
128 GetStubType());
129 Handle<Code> new_object = factory->NewCode(
130 desc, flags, masm.CodeObject(), NeedsImmovableCode());
131 return new_object;
132}
133
134
Leon Clarkee46be812010-01-19 14:06:41 +0000135Handle<Code> CodeStub::GetCode() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 Heap* heap = isolate()->heap();
Leon Clarkee46be812010-01-19 14:06:41 +0000137 Code* code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
139 : FindCodeInCache(&code)) {
140 DCHECK(GetCodeKind() == code->kind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100141 return Handle<Code>(code);
142 }
143
144 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000146
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 Handle<Code> new_object = GenerateCode();
148 new_object->set_stub_key(GetKey());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100149 FinishCode(new_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 RecordCodeGeneration(new_object);
151
152#ifdef ENABLE_DISASSEMBLER
153 if (FLAG_print_code_stubs) {
154 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
155 OFStream os(trace_scope.file());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 std::ostringstream name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 name << *this;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158 new_object->Disassemble(name.str().c_str(), os);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000159 os << "\n";
160 }
161#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000162
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100163 if (UseSpecialCache()) {
164 AddToSpecialCache(new_object);
165 } else {
166 // Update the dictionary and the root in Heap.
167 Handle<UnseededNumberDictionary> dict =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 UnseededNumberDictionary::AtNumberPut(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100169 Handle<UnseededNumberDictionary>(heap->code_stubs()),
170 GetKey(),
171 new_object);
172 heap->public_set_code_stubs(*dict);
173 }
Leon Clarkee46be812010-01-19 14:06:41 +0000174 code = *new_object;
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000176
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100177 Activate(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178 DCHECK(!NeedsImmovableCode() ||
179 heap->lo_space()->Contains(code) ||
180 heap->code_space()->FirstPage()->Contains(code->address()));
181 return Handle<Code>(code, isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000182}
183
184
Andrei Popescu31002712010-02-23 13:46:05 +0000185const char* CodeStub::MajorName(CodeStub::Major major_key,
186 bool allow_unknown_keys) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000187 switch (major_key) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000188#define DEF_CASE(name) case name: return #name "Stub";
Steve Blockd0582a62009-12-15 09:54:21 +0000189 CODE_STUB_LIST(DEF_CASE)
190#undef DEF_CASE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 case NoCache:
192 return "<NoCache>Stub";
193 case NUMBER_OF_IDS:
194 UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 return NULL;
196 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 return NULL;
198}
199
200
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400201void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 os << MajorName(MajorKey(), false);
203}
204
205
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206void CodeStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 PrintBaseName(os);
208 PrintState(os);
209}
210
211
212void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
213 DispatchedCall call) {
214 switch (MajorKeyFromKey(key)) {
215#define DEF_CASE(NAME) \
216 case NAME: { \
217 NAME##Stub stub(key, isolate); \
218 CodeStub* pstub = &stub; \
219 call(pstub, value_out); \
220 break; \
221 }
222 CODE_STUB_LIST(DEF_CASE)
223#undef DEF_CASE
224 case NUMBER_OF_IDS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 case NoCache:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400226 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 break;
228 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000229}
230
231
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232static void InitializeDescriptorDispatchedCall(CodeStub* stub,
233 void** value_out) {
234 CodeStubDescriptor* descriptor_out =
235 reinterpret_cast<CodeStubDescriptor*>(value_out);
236 stub->InitializeDescriptor(descriptor_out);
237 descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100238}
239
240
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
242 CodeStubDescriptor* desc) {
243 void** value_out = reinterpret_cast<void**>(desc);
244 Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
245}
246
247
248void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
249 Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
250 // Code stubs with special cache cannot be recreated from stub key.
251 *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
252}
253
254
255MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
256 HandleScope scope(isolate);
257 Handle<Code> code;
258 void** value_out = reinterpret_cast<void**>(&code);
259 Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
260 return scope.CloseAndEscape(code);
261}
262
263
264// static
265void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
266 // Generate the uninitialized versions of the stub.
267 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
268 for (int mode = NO_OVERWRITE; mode <= OVERWRITE_RIGHT; ++mode) {
269 BinaryOpICStub stub(isolate,
270 static_cast<Token::Value>(op),
271 static_cast<OverwriteMode>(mode));
272 stub.GetCode();
273 }
274 }
275
276 // Generate special versions of the stub.
277 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
278}
279
280
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400281void BinaryOpICStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 os << state();
283}
284
285
286// static
287void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
288 const BinaryOpICState& state) {
289 BinaryOpICStub stub(isolate, state);
290 stub.GetCode();
291}
292
293
294// static
295void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
296 // Generate special versions of the stub.
297 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
298}
299
300
301void BinaryOpICWithAllocationSiteStub::PrintState(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400302 std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 os << state();
304}
305
306
307// static
308void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
309 Isolate* isolate, const BinaryOpICState& state) {
310 if (state.CouldCreateAllocationMementos()) {
311 BinaryOpICWithAllocationSiteStub stub(isolate, state);
312 stub.GetCode();
313 }
314}
315
316
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400317void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318 os << "StringAddStub";
319 if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
320 os << "_CheckBoth";
321 } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
322 os << "_CheckLeft";
323 } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
324 os << "_CheckRight";
325 }
326 if (pretenure_flag() == TENURED) {
327 os << "_Tenured";
328 }
329}
330
331
332InlineCacheState CompareICStub::GetICState() const {
333 CompareICState::State state = Max(left(), right());
334 switch (state) {
335 case CompareICState::UNINITIALIZED:
336 return ::v8::internal::UNINITIALIZED;
337 case CompareICState::SMI:
338 case CompareICState::NUMBER:
339 case CompareICState::INTERNALIZED_STRING:
340 case CompareICState::STRING:
341 case CompareICState::UNIQUE_NAME:
342 case CompareICState::OBJECT:
343 case CompareICState::KNOWN_OBJECT:
344 return MONOMORPHIC;
345 case CompareICState::GENERIC:
346 return ::v8::internal::GENERIC;
347 }
348 UNREACHABLE();
349 return ::v8::internal::UNINITIALIZED;
350}
351
352
353Condition CompareICStub::GetCondition() const {
354 return CompareIC::ComputeCondition(op());
355}
356
357
358void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
359 DCHECK(*known_map_ != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100360 Isolate* isolate = new_object->GetIsolate();
361 Factory* factory = isolate->factory();
362 return Map::UpdateCodeCache(known_map_,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 strict() ?
364 factory->strict_compare_ic_string() :
365 factory->compare_ic_string(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100366 new_object);
367}
368
369
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
371 Factory* factory = isolate()->factory();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100372 Code::Flags flags = Code::ComputeFlags(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 GetCodeKind(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100374 UNINITIALIZED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375 DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100376 Handle<Object> probe(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 known_map_->FindInCodeCache(
378 strict() ?
379 *factory->strict_compare_ic_string() :
380 *factory->compare_ic_string(),
381 flags),
382 isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100383 if (probe->IsCode()) {
384 *code_out = Code::cast(*probe);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385#ifdef DEBUG
386 CompareICStub decode((*code_out)->stub_key(), isolate());
387 DCHECK(op() == decode.op());
388 DCHECK(left() == decode.left());
389 DCHECK(right() == decode.right());
390 DCHECK(state() == decode.state());
391#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100392 return true;
393 }
394 return false;
395}
396
397
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398void CompareICStub::Generate(MacroAssembler* masm) {
399 switch (state()) {
400 case CompareICState::UNINITIALIZED:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100401 GenerateMiss(masm);
402 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000403 case CompareICState::SMI:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100404 GenerateSmis(masm);
405 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 case CompareICState::NUMBER:
407 GenerateNumbers(masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100408 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 case CompareICState::STRING:
Ben Murdoch257744e2011-11-30 15:57:28 +0000410 GenerateStrings(masm);
411 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000412 case CompareICState::INTERNALIZED_STRING:
413 GenerateInternalizedStrings(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000414 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415 case CompareICState::UNIQUE_NAME:
416 GenerateUniqueNames(masm);
417 break;
418 case CompareICState::OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100419 GenerateObjects(masm);
420 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421 case CompareICState::KNOWN_OBJECT:
422 DCHECK(*known_map_ != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100423 GenerateKnownObjects(masm);
424 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 case CompareICState::GENERIC:
426 GenerateGeneric(masm);
427 break;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100428 }
429}
430
431
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432void CompareNilICStub::UpdateStatus(Handle<Object> object) {
433 State state = this->state();
434 DCHECK(!state.Contains(GENERIC));
435 State old_state = state;
436 if (object->IsNull()) {
437 state.Add(NULL_TYPE);
438 } else if (object->IsUndefined()) {
439 state.Add(UNDEFINED);
440 } else if (object->IsUndetectableObject() ||
441 object->IsOddball() ||
442 !object->IsHeapObject()) {
443 state.RemoveAll();
444 state.Add(GENERIC);
445 } else if (IsMonomorphic()) {
446 state.RemoveAll();
447 state.Add(GENERIC);
448 } else {
449 state.Add(MONOMORPHIC_MAP);
450 }
451 TraceTransition(old_state, state);
452 set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
453}
454
455
456template<class StateType>
457void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
458 // Note: Although a no-op transition is semantically OK, it is hinting at a
459 // bug somewhere in our state transition machinery.
460 DCHECK(from != to);
461 if (!FLAG_trace_ic) return;
462 OFStream os(stdout);
463 os << "[";
464 PrintBaseName(os);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400465 os << ": " << from << "=>" << to << "]" << std::endl;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000466}
467
468
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400469void CompareNilICStub::PrintBaseName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 CodeStub::PrintBaseName(os);
471 os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
472}
473
474
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475void CompareNilICStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 os << state();
477}
478
479
480// TODO(svenpanne) Make this a real infix_ostream_iterator.
481class SimpleListPrinter {
482 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400483 explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484
485 void Add(const char* s) {
486 if (first_) {
487 first_ = false;
488 } else {
489 os_ << ",";
490 }
491 os_ << s;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100492 }
493
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400495 std::ostream& os_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000496 bool first_;
497};
498
499
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400500std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 os << "(";
502 SimpleListPrinter p(os);
503 if (s.IsEmpty()) p.Add("None");
504 if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
505 if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
506 if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
507 if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
508 return os << ")";
509}
510
511
512Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
513 State state = this->state();
514 if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
515
516 Type* result = Type::None(zone);
517 if (state.Contains(CompareNilICStub::UNDEFINED)) {
518 result = Type::Union(result, Type::Undefined(zone), zone);
519 }
520 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
521 result = Type::Union(result, Type::Null(zone), zone);
522 }
523 if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
524 Type* type =
525 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
526 result = Type::Union(result, type, zone);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100527 }
528
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 return result;
530}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100531
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532
533Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
534 Type* output_type = GetType(zone, map);
535 Type* nil_type =
536 nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
537 return Type::Union(output_type, nil_type, zone);
538}
539
540
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400541void CallIC_ArrayStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000542 os << state() << " (Array)";
543}
544
545
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400546void CallICStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 os << state();
548}
549
550
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400551void InstanceofStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 os << "InstanceofStub";
553 if (HasArgsInRegisters()) os << "_REGS";
554 if (HasCallSiteInlineCheck()) os << "_INLINE";
555 if (ReturnTrueFalseObject()) os << "_TRUEFALSE";
Ben Murdoch086aeea2011-05-13 15:57:08 +0100556}
557
558
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100559void JSEntryStub::FinishCode(Handle<Code> code) {
560 Handle<FixedArray> handler_table =
561 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
562 handler_table->set(0, Smi::FromInt(handler_offset_));
563 code->set_handler_table(*handler_table);
564}
565
566
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567void LoadFastElementStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
568 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
569}
570
571
572void LoadDictionaryElementStub::InitializeDescriptor(
573 CodeStubDescriptor* descriptor) {
574 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
575}
576
577
578void KeyedLoadGenericStub::InitializeDescriptor(
579 CodeStubDescriptor* descriptor) {
580 descriptor->Initialize(
581 Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
582}
583
584
585void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
586 if (kind() == Code::STORE_IC) {
587 descriptor->Initialize(FUNCTION_ADDR(StoreIC_MissFromStubFailure));
588 } else if (kind() == Code::KEYED_LOAD_IC) {
589 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
590 }
591}
592
593
594CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
595 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400596 if (FLAG_vector_ics) {
597 return VectorLoadICDescriptor(isolate());
598 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599 return LoadDescriptor(isolate());
600 } else {
601 DCHECK_EQ(Code::STORE_IC, kind());
602 return StoreDescriptor(isolate());
603 }
604}
605
606
607void StoreFastElementStub::InitializeDescriptor(
608 CodeStubDescriptor* descriptor) {
609 descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
610}
611
612
613void ElementsTransitionAndStoreStub::InitializeDescriptor(
614 CodeStubDescriptor* descriptor) {
615 descriptor->Initialize(FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss));
616}
617
618
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400619CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor() {
620 return StoreTransitionDescriptor(isolate());
621}
622
623
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624static void InitializeVectorLoadStub(Isolate* isolate,
625 CodeStubDescriptor* descriptor,
626 Address deoptimization_handler) {
627 DCHECK(FLAG_vector_ics);
628 descriptor->Initialize(deoptimization_handler);
629}
630
631
632void VectorLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
633 InitializeVectorLoadStub(isolate(), descriptor,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400634 FUNCTION_ADDR(LoadIC_MissFromStubFailure));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000635}
636
637
638void VectorKeyedLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400639 InitializeVectorLoadStub(isolate(), descriptor,
640 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641}
642
643
644void MegamorphicLoadStub::InitializeDescriptor(CodeStubDescriptor* d) {}
645
646
647void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
648 descriptor->Initialize(
649 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
650}
651
652
653void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
654
655
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
657 NumberToStringDescriptor call_descriptor(isolate());
658 descriptor->Initialize(
659 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
660}
661
662
663void FastCloneShallowArrayStub::InitializeDescriptor(
664 CodeStubDescriptor* descriptor) {
665 FastCloneShallowArrayDescriptor call_descriptor(isolate());
666 descriptor->Initialize(
667 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
668}
669
670
671void FastCloneShallowObjectStub::InitializeDescriptor(
672 CodeStubDescriptor* descriptor) {
673 FastCloneShallowObjectDescriptor call_descriptor(isolate());
674 descriptor->Initialize(
675 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
676}
677
678
679void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
680
681
682void RegExpConstructResultStub::InitializeDescriptor(
683 CodeStubDescriptor* descriptor) {
684 descriptor->Initialize(
685 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
686}
687
688
689void TransitionElementsKindStub::InitializeDescriptor(
690 CodeStubDescriptor* descriptor) {
691 descriptor->Initialize(
692 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
693}
694
695
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400696void AllocateHeapNumberStub::InitializeDescriptor(
697 CodeStubDescriptor* descriptor) {
698 descriptor->Initialize(
699 Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
700}
701
702
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
704 descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
705 descriptor->SetMissHandler(
706 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
707}
708
709
710void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
711 descriptor->Initialize(FUNCTION_ADDR(ToBooleanIC_Miss));
712 descriptor->SetMissHandler(
713 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
714}
715
716
717void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
718 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_Miss));
719 descriptor->SetMissHandler(
720 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
721}
722
723
724void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
725 CodeStubDescriptor* descriptor) {
726 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
727}
728
729
730void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
731 descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
732}
733
734
735void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
736 CreateAllocationSiteStub stub(isolate);
737 stub.GetCode();
738}
739
740
741void StoreElementStub::Generate(MacroAssembler* masm) {
742 switch (elements_kind()) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000743 case FAST_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744 case FAST_HOLEY_ELEMENTS:
745 case FAST_SMI_ELEMENTS:
746 case FAST_HOLEY_SMI_ELEMENTS:
Ben Murdoch589d6972011-11-30 16:04:58 +0000747 case FAST_DOUBLE_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 case FAST_HOLEY_DOUBLE_ELEMENTS:
749#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
750 case EXTERNAL_##TYPE##_ELEMENTS: \
751 case TYPE##_ELEMENTS:
752
753 TYPED_ARRAYS(TYPED_ARRAY_CASE)
754#undef TYPED_ARRAY_CASE
755 UNREACHABLE();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000756 break;
Ben Murdoch589d6972011-11-30 16:04:58 +0000757 case DICTIONARY_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000758 ElementHandlerCompiler::GenerateStoreSlow(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000759 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760 case SLOPPY_ARGUMENTS_ELEMENTS:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000761 UNREACHABLE();
762 break;
763 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000764}
765
766
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000767void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
768 switch (type()) {
769 case READ_ELEMENT:
770 GenerateReadElement(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000771 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000772 case NEW_SLOPPY_FAST:
773 GenerateNewSloppyFast(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000774 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775 case NEW_SLOPPY_SLOW:
776 GenerateNewSloppySlow(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000777 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778 case NEW_STRICT:
779 GenerateNewStrict(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000780 break;
781 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000782}
783
784
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400785void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000786 os << "ArgumentsAccessStub_";
787 switch (type()) {
788 case READ_ELEMENT:
789 os << "ReadElement";
790 break;
791 case NEW_SLOPPY_FAST:
792 os << "NewSloppyFast";
793 break;
794 case NEW_SLOPPY_SLOW:
795 os << "NewSloppySlow";
796 break;
797 case NEW_STRICT:
798 os << "NewStrict";
799 break;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000800 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801 return;
Ben Murdoch257744e2011-11-30 15:57:28 +0000802}
803
804
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400805void CallFunctionStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806 os << "CallFunctionStub_Args" << argc();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100807}
808
809
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400810void CallConstructStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000811 os << "CallConstructStub";
812 if (RecordCallTarget()) os << "_Recording";
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100813}
814
815
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400816void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 os << "ArrayConstructorStub";
818 switch (argument_count()) {
819 case ANY:
820 os << "_Any";
821 break;
822 case NONE:
823 os << "_None";
824 break;
825 case ONE:
826 os << "_One";
827 break;
828 case MORE_THAN_ONE:
829 os << "_More_Than_One";
830 break;
831 }
832 return;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000833}
834
835
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400836std::ostream& ArrayConstructorStubBase::BasePrintName(
837 std::ostream& os, // NOLINT
838 const char* name) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 os << name << "_" << ElementsKindToString(elements_kind());
840 if (override_mode() == DISABLE_ALLOCATION_SITES) {
841 os << "_DISABLE_ALLOCATION_SITES";
842 }
843 return os;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000844}
845
846
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
848 Types new_types = types();
849 Types old_types = new_types;
850 bool to_boolean_value = new_types.UpdateStatus(object);
851 TraceTransition(old_types, new_types);
852 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToByte()));
853 return to_boolean_value;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000854}
855
856
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400857void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000858 os << types();
859}
860
861
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 os << "(";
864 SimpleListPrinter p(os);
865 if (s.IsEmpty()) p.Add("None");
866 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
867 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
868 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
869 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
870 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
871 if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
872 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
873 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
874 return os << ")";
875}
876
877
878bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000879 if (object->IsUndefined()) {
880 Add(UNDEFINED);
881 return false;
882 } else if (object->IsBoolean()) {
883 Add(BOOLEAN);
884 return object->IsTrue();
885 } else if (object->IsNull()) {
886 Add(NULL_TYPE);
887 return false;
888 } else if (object->IsSmi()) {
889 Add(SMI);
890 return Smi::cast(*object)->value() != 0;
891 } else if (object->IsSpecObject()) {
892 Add(SPEC_OBJECT);
893 return !object->IsUndetectableObject();
894 } else if (object->IsString()) {
895 Add(STRING);
896 return !object->IsUndetectableObject() &&
897 String::cast(*object)->length() != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000898 } else if (object->IsSymbol()) {
899 Add(SYMBOL);
900 return true;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000901 } else if (object->IsHeapNumber()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 DCHECK(!object->IsUndetectableObject());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000903 Add(HEAP_NUMBER);
904 double value = HeapNumber::cast(*object)->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 return value != 0 && !std::isnan(value);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000906 } else {
907 // We should never see an internal object at runtime here!
908 UNREACHABLE();
909 return true;
910 }
911}
912
913
914bool ToBooleanStub::Types::NeedsMap() const {
915 return Contains(ToBooleanStub::SPEC_OBJECT)
916 || Contains(ToBooleanStub::STRING)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 || Contains(ToBooleanStub::SYMBOL)
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000918 || Contains(ToBooleanStub::HEAP_NUMBER);
919}
920
921
922bool ToBooleanStub::Types::CanBeUndetectable() const {
923 return Contains(ToBooleanStub::SPEC_OBJECT)
924 || Contains(ToBooleanStub::STRING);
925}
926
927
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000928void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
929 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
930 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
931 stub1.GetCode();
932 stub2.GetCode();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100933}
934
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000935
936void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
937 intptr_t stack_pointer,
938 Isolate* isolate) {
939 FunctionEntryHook entry_hook = isolate->function_entry_hook();
940 DCHECK(entry_hook != NULL);
941 entry_hook(function, stack_pointer);
942}
943
944
945ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
946 : PlatformCodeStub(isolate) {
947 minor_key_ = ArgumentCountBits::encode(ANY);
948 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
949}
950
951
952ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
953 int argument_count)
954 : PlatformCodeStub(isolate) {
955 if (argument_count == 0) {
956 minor_key_ = ArgumentCountBits::encode(NONE);
957 } else if (argument_count == 1) {
958 minor_key_ = ArgumentCountBits::encode(ONE);
959 } else if (argument_count >= 2) {
960 minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
961 } else {
962 UNREACHABLE();
963 }
964 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
965}
966
967
968InternalArrayConstructorStub::InternalArrayConstructorStub(
969 Isolate* isolate) : PlatformCodeStub(isolate) {
970 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
971}
972
973
Steve Blocka7e24c12009-10-30 11:49:00 +0000974} } // namespace v8::internal