blob: 1754288b6ed751b066519c6871cf6e0b1380e424 [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 Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/compiler/code-stub-assembler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#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"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016#include "src/parsing/parser.h"
17#include "src/profiler/cpu-profiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000018
19namespace v8 {
20namespace internal {
21
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023RUNTIME_FUNCTION(UnexpectedStubMiss) {
24 FATAL("Unexpected deopt of a stub");
25 return Smi::FromInt(0);
26}
27
28
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
30 : call_descriptor_(stub->GetCallInterfaceDescriptor()),
31 stack_parameter_count_(no_reg),
32 hint_stack_parameter_count_(-1),
33 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
34 deoptimization_handler_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035 miss_handler_(),
36 has_miss_handler_(false) {
37 stub->InitializeDescriptor(this);
38}
39
40
41CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
42 : stack_parameter_count_(no_reg),
43 hint_stack_parameter_count_(-1),
44 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
45 deoptimization_handler_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046 miss_handler_(),
47 has_miss_handler_(false) {
48 CodeStub::InitializeDescriptor(isolate, stub_key, this);
49}
50
51
52void CodeStubDescriptor::Initialize(Address deoptimization_handler,
53 int hint_stack_parameter_count,
54 StubFunctionMode function_mode) {
55 deoptimization_handler_ = deoptimization_handler;
56 hint_stack_parameter_count_ = hint_stack_parameter_count;
57 function_mode_ = function_mode;
58}
59
60
61void CodeStubDescriptor::Initialize(Register stack_parameter_count,
62 Address deoptimization_handler,
63 int hint_stack_parameter_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 StubFunctionMode function_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
66 stack_parameter_count_ = stack_parameter_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067}
68
69
Leon Clarkee46be812010-01-19 14:06:41 +000070bool CodeStub::FindCodeInCache(Code** code_out) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
72 int index = stubs->FindEntry(GetKey());
Ben Murdochc7cc0282012-03-05 14:35:55 +000073 if (index != UnseededNumberDictionary::kNotFound) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074 *code_out = Code::cast(stubs->ValueAt(index));
Leon Clarkee46be812010-01-19 14:06:41 +000075 return true;
Steve Blockd0582a62009-12-15 09:54:21 +000076 }
Leon Clarkee46be812010-01-19 14:06:41 +000077 return false;
78}
Steve Blockd0582a62009-12-15 09:54:21 +000079
Leon Clarkee46be812010-01-19 14:06:41 +000080
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081void CodeStub::RecordCodeGeneration(Handle<Code> code) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082 std::ostringstream os;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 os << *this;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084 PROFILE(isolate(),
85 CodeCreateEvent(Logger::STUB_TAG, *code, os.str().c_str()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086 Counters* counters = isolate()->counters();
Steve Block44f0eee2011-05-26 01:26:41 +010087 counters->total_stubs_code_size()->Increment(code->instruction_size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088#ifdef DEBUG
89 code->VerifyEmbeddedObjects();
90#endif
Leon Clarkee46be812010-01-19 14:06:41 +000091}
92
93
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094Code::Kind CodeStub::GetCodeKind() const {
Steve Block6ded16b2010-05-10 14:33:55 +010095 return Code::STUB;
96}
97
98
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
100 Handle<Code> ic = GetCode();
101 ic = isolate()->factory()->CopyCode(ic);
102 ic->FindAndReplace(pattern);
103 RecordCodeGeneration(ic);
104 return ic;
105}
106
107
108Handle<Code> PlatformCodeStub::GenerateCode() {
109 Factory* factory = isolate()->factory();
110
111 // Generate the new code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 MacroAssembler masm(isolate(), NULL, 256, CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 {
115 // Update the static counter each time a new code stub is generated.
116 isolate()->counters()->code_stubs()->Increment();
117
118 // Generate the code for the stub.
119 masm.set_generating_stub(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400120 // TODO(yangguo): remove this once we can serialize IC stubs.
121 masm.enable_serializer();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 NoCurrentFrameScope scope(&masm);
123 Generate(&masm);
124 }
125
126 // Create the code object.
127 CodeDesc desc;
128 masm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 // Copy the generated code into a heap object.
130 Code::Flags flags = Code::ComputeFlags(
131 GetCodeKind(),
132 GetICState(),
133 GetExtraICState(),
134 GetStubType());
135 Handle<Code> new_object = factory->NewCode(
136 desc, flags, masm.CodeObject(), NeedsImmovableCode());
137 return new_object;
138}
139
140
Leon Clarkee46be812010-01-19 14:06:41 +0000141Handle<Code> CodeStub::GetCode() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142 Heap* heap = isolate()->heap();
Leon Clarkee46be812010-01-19 14:06:41 +0000143 Code* code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
145 : FindCodeInCache(&code)) {
146 DCHECK(GetCodeKind() == code->kind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100147 return Handle<Code>(code);
148 }
149
150 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000152
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 Handle<Code> new_object = GenerateCode();
154 new_object->set_stub_key(GetKey());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100155 FinishCode(new_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156 RecordCodeGeneration(new_object);
157
158#ifdef ENABLE_DISASSEMBLER
159 if (FLAG_print_code_stubs) {
160 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
161 OFStream os(trace_scope.file());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 std::ostringstream name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163 name << *this;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400164 new_object->Disassemble(name.str().c_str(), os);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165 os << "\n";
166 }
167#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100169 if (UseSpecialCache()) {
170 AddToSpecialCache(new_object);
171 } else {
172 // Update the dictionary and the root in Heap.
173 Handle<UnseededNumberDictionary> dict =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 UnseededNumberDictionary::AtNumberPut(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100175 Handle<UnseededNumberDictionary>(heap->code_stubs()),
176 GetKey(),
177 new_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 heap->SetRootCodeStubs(*dict);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100179 }
Leon Clarkee46be812010-01-19 14:06:41 +0000180 code = *new_object;
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000182
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100183 Activate(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 DCHECK(!NeedsImmovableCode() ||
185 heap->lo_space()->Contains(code) ||
186 heap->code_space()->FirstPage()->Contains(code->address()));
187 return Handle<Code>(code, isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000188}
189
190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191const char* CodeStub::MajorName(CodeStub::Major major_key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 switch (major_key) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000193#define DEF_CASE(name) case name: return #name "Stub";
Steve Blockd0582a62009-12-15 09:54:21 +0000194 CODE_STUB_LIST(DEF_CASE)
195#undef DEF_CASE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 case NoCache:
197 return "<NoCache>Stub";
198 case NUMBER_OF_IDS:
199 UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 return NULL;
201 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 return NULL;
203}
204
205
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 os << MajorName(MajorKey());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208}
209
210
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211void CodeStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 PrintBaseName(os);
213 PrintState(os);
214}
215
216
217void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
218 DispatchedCall call) {
219 switch (MajorKeyFromKey(key)) {
220#define DEF_CASE(NAME) \
221 case NAME: { \
222 NAME##Stub stub(key, isolate); \
223 CodeStub* pstub = &stub; \
224 call(pstub, value_out); \
225 break; \
226 }
227 CODE_STUB_LIST(DEF_CASE)
228#undef DEF_CASE
229 case NUMBER_OF_IDS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 case NoCache:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 break;
233 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000234}
235
236
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237static void InitializeDescriptorDispatchedCall(CodeStub* stub,
238 void** value_out) {
239 CodeStubDescriptor* descriptor_out =
240 reinterpret_cast<CodeStubDescriptor*>(value_out);
241 stub->InitializeDescriptor(descriptor_out);
242 descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100243}
244
245
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
247 CodeStubDescriptor* desc) {
248 void** value_out = reinterpret_cast<void**>(desc);
249 Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
250}
251
252
253void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
254 Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
255 // Code stubs with special cache cannot be recreated from stub key.
256 *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
257}
258
259
260MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
261 HandleScope scope(isolate);
262 Handle<Code> code;
263 void** value_out = reinterpret_cast<void**>(&code);
264 Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
265 return scope.CloseAndEscape(code);
266}
267
268
269// static
270void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
271 // Generate the uninitialized versions of the stub.
272 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273 BinaryOpICStub stub(isolate, static_cast<Token::Value>(op), Strength::WEAK);
274 stub.GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 }
276
277 // Generate special versions of the stub.
278 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
279}
280
281
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400282void BinaryOpICStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 os << state();
284}
285
286
287// static
288void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
289 const BinaryOpICState& state) {
290 BinaryOpICStub stub(isolate, state);
291 stub.GetCode();
292}
293
294
295// static
296void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
297 // Generate special versions of the stub.
298 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
299}
300
301
302void BinaryOpICWithAllocationSiteStub::PrintState(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400303 std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304 os << state();
305}
306
307
308// static
309void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
310 Isolate* isolate, const BinaryOpICState& state) {
311 if (state.CouldCreateAllocationMementos()) {
312 BinaryOpICWithAllocationSiteStub stub(isolate, state);
313 stub.GetCode();
314 }
315}
316
317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags) {
319 switch (flags) {
320 case STRING_ADD_CHECK_NONE:
321 return os << "CheckNone";
322 case STRING_ADD_CHECK_LEFT:
323 return os << "CheckLeft";
324 case STRING_ADD_CHECK_RIGHT:
325 return os << "CheckRight";
326 case STRING_ADD_CHECK_BOTH:
327 return os << "CheckBoth";
328 case STRING_ADD_CONVERT_LEFT:
329 return os << "ConvertLeft";
330 case STRING_ADD_CONVERT_RIGHT:
331 return os << "ConvertRight";
332 case STRING_ADD_CONVERT:
333 break;
334 }
335 UNREACHABLE();
336 return os;
337}
338
339
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 os << "StringAddStub_" << flags() << "_" << pretenure_flag();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342}
343
344
345InlineCacheState CompareICStub::GetICState() const {
346 CompareICState::State state = Max(left(), right());
347 switch (state) {
348 case CompareICState::UNINITIALIZED:
349 return ::v8::internal::UNINITIALIZED;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 case CompareICState::BOOLEAN:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000351 case CompareICState::SMI:
352 case CompareICState::NUMBER:
353 case CompareICState::INTERNALIZED_STRING:
354 case CompareICState::STRING:
355 case CompareICState::UNIQUE_NAME:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 case CompareICState::RECEIVER:
357 case CompareICState::KNOWN_RECEIVER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358 return MONOMORPHIC;
359 case CompareICState::GENERIC:
360 return ::v8::internal::GENERIC;
361 }
362 UNREACHABLE();
363 return ::v8::internal::UNINITIALIZED;
364}
365
366
367Condition CompareICStub::GetCondition() const {
368 return CompareIC::ComputeCondition(op());
369}
370
371
372void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
373 DCHECK(*known_map_ != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100374 Isolate* isolate = new_object->GetIsolate();
375 Factory* factory = isolate->factory();
376 return Map::UpdateCodeCache(known_map_,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 strict() ?
378 factory->strict_compare_ic_string() :
379 factory->compare_ic_string(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100380 new_object);
381}
382
383
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
385 Factory* factory = isolate()->factory();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100386 Code::Flags flags = Code::ComputeFlags(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387 GetCodeKind(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100388 UNINITIALIZED);
389 Handle<Object> probe(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390 known_map_->FindInCodeCache(
391 strict() ?
392 *factory->strict_compare_ic_string() :
393 *factory->compare_ic_string(),
394 flags),
395 isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100396 if (probe->IsCode()) {
397 *code_out = Code::cast(*probe);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398#ifdef DEBUG
399 CompareICStub decode((*code_out)->stub_key(), isolate());
400 DCHECK(op() == decode.op());
401 DCHECK(left() == decode.left());
402 DCHECK(right() == decode.right());
403 DCHECK(state() == decode.state());
404#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100405 return true;
406 }
407 return false;
408}
409
410
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411void CompareICStub::Generate(MacroAssembler* masm) {
412 switch (state()) {
413 case CompareICState::UNINITIALIZED:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100414 GenerateMiss(masm);
415 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 case CompareICState::BOOLEAN:
417 GenerateBooleans(masm);
418 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419 case CompareICState::SMI:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100420 GenerateSmis(masm);
421 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 case CompareICState::NUMBER:
423 GenerateNumbers(masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100424 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 case CompareICState::STRING:
Ben Murdoch257744e2011-11-30 15:57:28 +0000426 GenerateStrings(masm);
427 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000428 case CompareICState::INTERNALIZED_STRING:
429 GenerateInternalizedStrings(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000430 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 case CompareICState::UNIQUE_NAME:
432 GenerateUniqueNames(masm);
433 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 case CompareICState::RECEIVER:
435 GenerateReceivers(masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100436 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000437 case CompareICState::KNOWN_RECEIVER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 DCHECK(*known_map_ != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 GenerateKnownReceivers(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100440 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441 case CompareICState::GENERIC:
442 GenerateGeneric(masm);
443 break;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100444 }
445}
446
447
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448void CompareNilICStub::UpdateStatus(Handle<Object> object) {
449 State state = this->state();
450 DCHECK(!state.Contains(GENERIC));
451 State old_state = state;
452 if (object->IsNull()) {
453 state.Add(NULL_TYPE);
454 } else if (object->IsUndefined()) {
455 state.Add(UNDEFINED);
456 } else if (object->IsUndetectableObject() ||
457 object->IsOddball() ||
458 !object->IsHeapObject()) {
459 state.RemoveAll();
460 state.Add(GENERIC);
461 } else if (IsMonomorphic()) {
462 state.RemoveAll();
463 state.Add(GENERIC);
464 } else {
465 state.Add(MONOMORPHIC_MAP);
466 }
467 TraceTransition(old_state, state);
468 set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
469}
470
471
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000472Handle<Code> TurboFanCodeStub::GenerateCode() {
473 const char* name = CodeStub::MajorName(MajorKey());
474 Zone zone;
475 CallInterfaceDescriptor descriptor(GetCallInterfaceDescriptor());
476 compiler::CodeStubAssembler assembler(isolate(), &zone, descriptor,
477 GetCodeKind(), name);
478 GenerateAssembly(&assembler);
479 return assembler.GenerateCode();
480}
481
482
483void StringLengthStub::GenerateAssembly(
484 compiler::CodeStubAssembler* assembler) const {
485 compiler::Node* value = assembler->Parameter(0);
486 compiler::Node* string =
487 assembler->LoadObjectField(value, JSValue::kValueOffset);
488 compiler::Node* result =
489 assembler->LoadObjectField(string, String::kLengthOffset);
490 assembler->Return(result);
491}
492
493
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494template<class StateType>
495void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
496 // Note: Although a no-op transition is semantically OK, it is hinting at a
497 // bug somewhere in our state transition machinery.
498 DCHECK(from != to);
499 if (!FLAG_trace_ic) return;
500 OFStream os(stdout);
501 os << "[";
502 PrintBaseName(os);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400503 os << ": " << from << "=>" << to << "]" << std::endl;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000504}
505
506
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400507void CompareNilICStub::PrintBaseName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 CodeStub::PrintBaseName(os);
509 os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
510}
511
512
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400513void CompareNilICStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 os << state();
515}
516
517
518// TODO(svenpanne) Make this a real infix_ostream_iterator.
519class SimpleListPrinter {
520 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400521 explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522
523 void Add(const char* s) {
524 if (first_) {
525 first_ = false;
526 } else {
527 os_ << ",";
528 }
529 os_ << s;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100530 }
531
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400533 std::ostream& os_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534 bool first_;
535};
536
537
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400538std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539 os << "(";
540 SimpleListPrinter p(os);
541 if (s.IsEmpty()) p.Add("None");
542 if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
543 if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
544 if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
545 if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
546 return os << ")";
547}
548
549
550Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
551 State state = this->state();
552 if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
553
554 Type* result = Type::None(zone);
555 if (state.Contains(CompareNilICStub::UNDEFINED)) {
556 result = Type::Union(result, Type::Undefined(zone), zone);
557 }
558 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
559 result = Type::Union(result, Type::Null(zone), zone);
560 }
561 if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
562 Type* type =
563 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
564 result = Type::Union(result, type, zone);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100565 }
566
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 return result;
568}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100569
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570
571Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
572 Type* output_type = GetType(zone, map);
573 Type* nil_type =
574 nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
575 return Type::Union(output_type, nil_type, zone);
576}
577
578
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400579void CallICStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 os << state();
581}
582
583
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100584void JSEntryStub::FinishCode(Handle<Code> code) {
585 Handle<FixedArray> handler_table =
586 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
587 handler_table->set(0, Smi::FromInt(handler_offset_));
588 code->set_handler_table(*handler_table);
589}
590
591
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592void LoadDictionaryElementStub::InitializeDescriptor(
593 CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 descriptor->Initialize(
595 FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596}
597
598
599void KeyedLoadGenericStub::InitializeDescriptor(
600 CodeStubDescriptor* descriptor) {
601 descriptor->Initialize(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 Runtime::FunctionForId(is_strong(language_mode())
603 ? Runtime::kKeyedGetPropertyStrong
604 : Runtime::kKeyedGetProperty)->entry);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605}
606
607
608void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
609 if (kind() == Code::STORE_IC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 descriptor->Initialize(FUNCTION_ADDR(Runtime_StoreIC_MissFromStubFailure));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 } else if (kind() == Code::KEYED_LOAD_IC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 descriptor->Initialize(
613 FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
614 } else if (kind() == Code::KEYED_STORE_IC) {
615 descriptor->Initialize(
616 FUNCTION_ADDR(Runtime_KeyedStoreIC_MissFromStubFailure));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 }
618}
619
620
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623 return LoadWithVectorDescriptor(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
626 return VectorStoreICDescriptor(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 }
628}
629
630
631void StoreFastElementStub::InitializeDescriptor(
632 CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 descriptor->Initialize(
634 FUNCTION_ADDR(Runtime_KeyedStoreIC_MissFromStubFailure));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000635}
636
637
638void ElementsTransitionAndStoreStub::InitializeDescriptor(
639 CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 descriptor->Initialize(
641 FUNCTION_ADDR(Runtime_ElementsTransitionAndStoreIC_Miss));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000642}
643
644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
646 descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400647}
648
649
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000650CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
651 const {
652 return VectorStoreTransitionDescriptor(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653}
654
655
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656CallInterfaceDescriptor
657ElementsTransitionAndStoreStub::GetCallInterfaceDescriptor() const {
658 return VectorStoreTransitionDescriptor(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659}
660
661
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663 descriptor->Initialize(Runtime::FunctionForId(Runtime::kNewClosure)->entry);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000664}
665
666
667void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
668
669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670void TypeofStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {}
671
672
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
674 NumberToStringDescriptor call_descriptor(isolate());
675 descriptor->Initialize(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 Runtime::FunctionForId(Runtime::kNumberToString)->entry);
677}
678
679
680void FastCloneRegExpStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
681 FastCloneRegExpDescriptor call_descriptor(isolate());
682 descriptor->Initialize(
683 Runtime::FunctionForId(Runtime::kCreateRegExpLiteral)->entry);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684}
685
686
687void FastCloneShallowArrayStub::InitializeDescriptor(
688 CodeStubDescriptor* descriptor) {
689 FastCloneShallowArrayDescriptor call_descriptor(isolate());
690 descriptor->Initialize(
691 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
692}
693
694
695void FastCloneShallowObjectStub::InitializeDescriptor(
696 CodeStubDescriptor* descriptor) {
697 FastCloneShallowObjectDescriptor call_descriptor(isolate());
698 descriptor->Initialize(
699 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
700}
701
702
703void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
704
705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
707
708
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000709void RegExpConstructResultStub::InitializeDescriptor(
710 CodeStubDescriptor* descriptor) {
711 descriptor->Initialize(
712 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
713}
714
715
716void TransitionElementsKindStub::InitializeDescriptor(
717 CodeStubDescriptor* descriptor) {
718 descriptor->Initialize(
719 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
720}
721
722
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400723void AllocateHeapNumberStub::InitializeDescriptor(
724 CodeStubDescriptor* descriptor) {
725 descriptor->Initialize(
726 Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
727}
728
729
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000730void AllocateMutableHeapNumberStub::InitializeDescriptor(
731 CodeStubDescriptor* descriptor) {
732 descriptor->Initialize();
733}
734
735
736void AllocateInNewSpaceStub::InitializeDescriptor(
737 CodeStubDescriptor* descriptor) {
738 descriptor->Initialize();
739}
740
741
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000742void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 descriptor->Initialize(FUNCTION_ADDR(Runtime_CompareNilIC_Miss));
744 descriptor->SetMissHandler(ExternalReference(
745 Runtime::FunctionForId(Runtime::kCompareNilIC_Miss), isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746}
747
748
749void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000750 descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss));
751 descriptor->SetMissHandler(ExternalReference(
752 Runtime::FunctionForId(Runtime::kToBooleanIC_Miss), isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753}
754
755
756void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 descriptor->Initialize(FUNCTION_ADDR(Runtime_BinaryOpIC_Miss));
758 descriptor->SetMissHandler(ExternalReference(
759 Runtime::FunctionForId(Runtime::kBinaryOpIC_Miss), isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760}
761
762
763void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
764 CodeStubDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 descriptor->Initialize(
766 FUNCTION_ADDR(Runtime_BinaryOpIC_MissWithAllocationSite));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000767}
768
769
770void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
771 descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
772}
773
774
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775void GrowArrayElementsStub::InitializeDescriptor(
776 CodeStubDescriptor* descriptor) {
777 descriptor->Initialize(
778 Runtime::FunctionForId(Runtime::kGrowArrayElements)->entry);
779}
780
781
782void TypeofStub::GenerateAheadOfTime(Isolate* isolate) {
783 TypeofStub stub(isolate);
784 stub.GetCode();
785}
786
787
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000788void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
789 CreateAllocationSiteStub stub(isolate);
790 stub.GetCode();
791}
792
793
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
795 CreateWeakCellStub stub(isolate);
796 stub.GetCode();
797}
798
799
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800void StoreElementStub::Generate(MacroAssembler* masm) {
801 switch (elements_kind()) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000802 case FAST_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000803 case FAST_HOLEY_ELEMENTS:
804 case FAST_SMI_ELEMENTS:
805 case FAST_HOLEY_SMI_ELEMENTS:
Ben Murdoch589d6972011-11-30 16:04:58 +0000806 case FAST_DOUBLE_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000807 case FAST_HOLEY_DOUBLE_ELEMENTS:
808#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000809 case TYPE##_ELEMENTS:
810
811 TYPED_ARRAYS(TYPED_ARRAY_CASE)
812#undef TYPED_ARRAY_CASE
813 UNREACHABLE();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000814 break;
Ben Murdoch589d6972011-11-30 16:04:58 +0000815 case DICTIONARY_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000816 ElementHandlerCompiler::GenerateStoreSlow(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000817 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
819 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000820 UNREACHABLE();
821 break;
822 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000823}
824
825
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826// static
827void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
828 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS, STANDARD_STORE)
829 .GetCode();
830 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS,
831 STORE_AND_GROW_NO_TRANSITION).GetCode();
832 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
833 ElementsKind kind = static_cast<ElementsKind>(i);
834 StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode();
835 StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION)
836 .GetCode();
837 }
838}
839
840
841void RestParamAccessStub::Generate(MacroAssembler* masm) { GenerateNew(masm); }
842
843
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000844void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
845 switch (type()) {
846 case READ_ELEMENT:
847 GenerateReadElement(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000848 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000849 case NEW_SLOPPY_FAST:
850 GenerateNewSloppyFast(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000851 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 case NEW_SLOPPY_SLOW:
853 GenerateNewSloppySlow(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000854 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 case NEW_STRICT:
856 GenerateNewStrict(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000857 break;
858 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000859}
860
861
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 os << "ArgumentsAccessStub_";
864 switch (type()) {
865 case READ_ELEMENT:
866 os << "ReadElement";
867 break;
868 case NEW_SLOPPY_FAST:
869 os << "NewSloppyFast";
870 break;
871 case NEW_SLOPPY_SLOW:
872 os << "NewSloppySlow";
873 break;
874 case NEW_STRICT:
875 os << "NewStrict";
876 break;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000877 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 return;
Ben Murdoch257744e2011-11-30 15:57:28 +0000879}
880
881
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882void RestParamAccessStub::PrintName(std::ostream& os) const { // NOLINT
883 os << "RestParamAccessStub_";
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100884}
885
886
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400887void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 os << "ArrayConstructorStub";
889 switch (argument_count()) {
890 case ANY:
891 os << "_Any";
892 break;
893 case NONE:
894 os << "_None";
895 break;
896 case ONE:
897 os << "_One";
898 break;
899 case MORE_THAN_ONE:
900 os << "_More_Than_One";
901 break;
902 }
903 return;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000904}
905
906
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400907std::ostream& ArrayConstructorStubBase::BasePrintName(
908 std::ostream& os, // NOLINT
909 const char* name) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 os << name << "_" << ElementsKindToString(elements_kind());
911 if (override_mode() == DISABLE_ALLOCATION_SITES) {
912 os << "_DISABLE_ALLOCATION_SITES";
913 }
914 return os;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000915}
916
917
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
919 Types new_types = types();
920 Types old_types = new_types;
921 bool to_boolean_value = new_types.UpdateStatus(object);
922 TraceTransition(old_types, new_types);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924 return to_boolean_value;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000925}
926
927
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400928void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000929 os << types();
930}
931
932
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400933std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934 os << "(";
935 SimpleListPrinter p(os);
936 if (s.IsEmpty()) p.Add("None");
937 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
938 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
939 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
940 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
941 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
942 if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
943 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
944 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 if (s.Contains(ToBooleanStub::SIMD_VALUE)) p.Add("SimdValue");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 return os << ")";
947}
948
949
950bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000951 if (object->IsUndefined()) {
952 Add(UNDEFINED);
953 return false;
954 } else if (object->IsBoolean()) {
955 Add(BOOLEAN);
956 return object->IsTrue();
957 } else if (object->IsNull()) {
958 Add(NULL_TYPE);
959 return false;
960 } else if (object->IsSmi()) {
961 Add(SMI);
962 return Smi::cast(*object)->value() != 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963 } else if (object->IsJSReceiver()) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000964 Add(SPEC_OBJECT);
965 return !object->IsUndetectableObject();
966 } else if (object->IsString()) {
967 Add(STRING);
968 return !object->IsUndetectableObject() &&
969 String::cast(*object)->length() != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 } else if (object->IsSymbol()) {
971 Add(SYMBOL);
972 return true;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000973 } else if (object->IsHeapNumber()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000974 DCHECK(!object->IsUndetectableObject());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000975 Add(HEAP_NUMBER);
976 double value = HeapNumber::cast(*object)->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000977 return value != 0 && !std::isnan(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000978 } else if (object->IsSimd128Value()) {
979 Add(SIMD_VALUE);
980 return true;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000981 } else {
982 // We should never see an internal object at runtime here!
983 UNREACHABLE();
984 return true;
985 }
986}
987
988
989bool ToBooleanStub::Types::NeedsMap() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000990 return Contains(ToBooleanStub::SPEC_OBJECT) ||
991 Contains(ToBooleanStub::STRING) || Contains(ToBooleanStub::SYMBOL) ||
992 Contains(ToBooleanStub::HEAP_NUMBER) ||
993 Contains(ToBooleanStub::SIMD_VALUE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000994}
995
996
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000997void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
998 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
999 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
1000 stub1.GetCode();
1001 stub2.GetCode();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001002}
1003
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004
1005void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
1006 intptr_t stack_pointer,
1007 Isolate* isolate) {
1008 FunctionEntryHook entry_hook = isolate->function_entry_hook();
1009 DCHECK(entry_hook != NULL);
1010 entry_hook(function, stack_pointer);
1011}
1012
1013
1014ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
1015 : PlatformCodeStub(isolate) {
1016 minor_key_ = ArgumentCountBits::encode(ANY);
1017 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1018}
1019
1020
1021ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
1022 int argument_count)
1023 : PlatformCodeStub(isolate) {
1024 if (argument_count == 0) {
1025 minor_key_ = ArgumentCountBits::encode(NONE);
1026 } else if (argument_count == 1) {
1027 minor_key_ = ArgumentCountBits::encode(ONE);
1028 } else if (argument_count >= 2) {
1029 minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
1030 } else {
1031 UNREACHABLE();
1032 }
1033 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1034}
1035
1036
1037InternalArrayConstructorStub::InternalArrayConstructorStub(
1038 Isolate* isolate) : PlatformCodeStub(isolate) {
1039 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1040}
1041
1042
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043Representation RepresentationFromType(Type* type) {
1044 if (type->Is(Type::UntaggedIntegral())) {
1045 return Representation::Integer32();
1046 }
1047
1048 if (type->Is(Type::TaggedSigned())) {
1049 return Representation::Smi();
1050 }
1051
1052 if (type->Is(Type::UntaggedPointer())) {
1053 return Representation::External();
1054 }
1055
1056 DCHECK(!type->Is(Type::Untagged()));
1057 return Representation::Tagged();
1058}
1059
1060} // namespace internal
1061} // namespace v8