1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #include "src/bootstrapper.h"
8 #include "src/code-stubs.h"
9 #include "src/cpu-profiler.h"
10 #include "src/stub-cache.h"
11 #include "src/factory.h"
12 #include "src/gdb-jit.h"
13 #include "src/macro-assembler.h"
14
15 namespace v8 {
16 namespace internal {
17
18
CodeStubInterfaceDescriptor()19 CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
20 : register_param_count_(-1),
21 stack_parameter_count_(no_reg),
22 hint_stack_parameter_count_(-1),
23 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
24 register_params_(NULL),
25 register_param_representations_(NULL),
26 deoptimization_handler_(NULL),
27 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
28 miss_handler_(),
29 has_miss_handler_(false) { }
30
31
FindCodeInCache(Code ** code_out)32 bool CodeStub::FindCodeInCache(Code** code_out) {
33 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
34 int index = stubs->FindEntry(GetKey());
35 if (index != UnseededNumberDictionary::kNotFound) {
36 *code_out = Code::cast(stubs->ValueAt(index));
37 return true;
38 }
39 return false;
40 }
41
42
GetName()43 SmartArrayPointer<const char> CodeStub::GetName() {
44 char buffer[100];
45 NoAllocationStringAllocator allocator(buffer,
46 static_cast<unsigned>(sizeof(buffer)));
47 StringStream stream(&allocator);
48 PrintName(&stream);
49 return stream.ToCString();
50 }
51
52
RecordCodeGeneration(Handle<Code> code)53 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
54 IC::RegisterWeakMapDependency(code);
55 SmartArrayPointer<const char> name = GetName();
56 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, name.get()));
57 GDBJIT(AddCode(GDBJITInterface::STUB, name.get(), *code));
58 Counters* counters = isolate()->counters();
59 counters->total_stubs_code_size()->Increment(code->instruction_size());
60 }
61
62
GetCodeKind() const63 Code::Kind CodeStub::GetCodeKind() const {
64 return Code::STUB;
65 }
66
67
GetCodeCopy(const Code::FindAndReplacePattern & pattern)68 Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
69 Handle<Code> ic = GetCode();
70 ic = isolate()->factory()->CopyCode(ic);
71 ic->FindAndReplace(pattern);
72 RecordCodeGeneration(ic);
73 return ic;
74 }
75
76
GenerateCode()77 Handle<Code> PlatformCodeStub::GenerateCode() {
78 Factory* factory = isolate()->factory();
79
80 // Generate the new code.
81 MacroAssembler masm(isolate(), NULL, 256);
82
83 {
84 // Update the static counter each time a new code stub is generated.
85 isolate()->counters()->code_stubs()->Increment();
86
87 // Generate the code for the stub.
88 masm.set_generating_stub(true);
89 NoCurrentFrameScope scope(&masm);
90 Generate(&masm);
91 }
92
93 // Create the code object.
94 CodeDesc desc;
95 masm.GetCode(&desc);
96
97 // Copy the generated code into a heap object.
98 Code::Flags flags = Code::ComputeFlags(
99 GetCodeKind(),
100 GetICState(),
101 GetExtraICState(),
102 GetStubType());
103 Handle<Code> new_object = factory->NewCode(
104 desc, flags, masm.CodeObject(), NeedsImmovableCode());
105 return new_object;
106 }
107
108
GetCode()109 Handle<Code> CodeStub::GetCode() {
110 Heap* heap = isolate()->heap();
111 Code* code;
112 if (UseSpecialCache()
113 ? FindCodeInSpecialCache(&code)
114 : FindCodeInCache(&code)) {
115 ASSERT(GetCodeKind() == code->kind());
116 return Handle<Code>(code);
117 }
118
119 {
120 HandleScope scope(isolate());
121
122 Handle<Code> new_object = GenerateCode();
123 new_object->set_major_key(MajorKey());
124 FinishCode(new_object);
125 RecordCodeGeneration(new_object);
126
127 #ifdef ENABLE_DISASSEMBLER
128 if (FLAG_print_code_stubs) {
129 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
130 new_object->Disassemble(GetName().get(), trace_scope.file());
131 PrintF(trace_scope.file(), "\n");
132 }
133 #endif
134
135 if (UseSpecialCache()) {
136 AddToSpecialCache(new_object);
137 } else {
138 // Update the dictionary and the root in Heap.
139 Handle<UnseededNumberDictionary> dict =
140 UnseededNumberDictionary::AtNumberPut(
141 Handle<UnseededNumberDictionary>(heap->code_stubs()),
142 GetKey(),
143 new_object);
144 heap->public_set_code_stubs(*dict);
145 }
146 code = *new_object;
147 }
148
149 Activate(code);
150 ASSERT(!NeedsImmovableCode() ||
151 heap->lo_space()->Contains(code) ||
152 heap->code_space()->FirstPage()->Contains(code->address()));
153 return Handle<Code>(code, isolate());
154 }
155
156
MajorName(CodeStub::Major major_key,bool allow_unknown_keys)157 const char* CodeStub::MajorName(CodeStub::Major major_key,
158 bool allow_unknown_keys) {
159 switch (major_key) {
160 #define DEF_CASE(name) case name: return #name "Stub";
161 CODE_STUB_LIST(DEF_CASE)
162 #undef DEF_CASE
163 case UninitializedMajorKey: return "<UninitializedMajorKey>Stub";
164 default:
165 if (!allow_unknown_keys) {
166 UNREACHABLE();
167 }
168 return NULL;
169 }
170 }
171
172
PrintBaseName(StringStream * stream)173 void CodeStub::PrintBaseName(StringStream* stream) {
174 stream->Add("%s", MajorName(MajorKey(), false));
175 }
176
177
PrintName(StringStream * stream)178 void CodeStub::PrintName(StringStream* stream) {
179 PrintBaseName(stream);
180 PrintState(stream);
181 }
182
183
184 // static
GenerateAheadOfTime(Isolate * isolate)185 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
186 // Generate the uninitialized versions of the stub.
187 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
188 for (int mode = NO_OVERWRITE; mode <= OVERWRITE_RIGHT; ++mode) {
189 BinaryOpICStub stub(isolate,
190 static_cast<Token::Value>(op),
191 static_cast<OverwriteMode>(mode));
192 stub.GetCode();
193 }
194 }
195
196 // Generate special versions of the stub.
197 BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
198 }
199
200
PrintState(StringStream * stream)201 void BinaryOpICStub::PrintState(StringStream* stream) {
202 state_.Print(stream);
203 }
204
205
206 // static
GenerateAheadOfTime(Isolate * isolate,const BinaryOpIC::State & state)207 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
208 const BinaryOpIC::State& state) {
209 BinaryOpICStub stub(isolate, state);
210 stub.GetCode();
211 }
212
213
214 // static
GenerateAheadOfTime(Isolate * isolate)215 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
216 // Generate special versions of the stub.
217 BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
218 }
219
220
PrintState(StringStream * stream)221 void BinaryOpICWithAllocationSiteStub::PrintState(StringStream* stream) {
222 state_.Print(stream);
223 }
224
225
226 // static
GenerateAheadOfTime(Isolate * isolate,const BinaryOpIC::State & state)227 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
228 Isolate* isolate, const BinaryOpIC::State& state) {
229 if (state.CouldCreateAllocationMementos()) {
230 BinaryOpICWithAllocationSiteStub stub(isolate, state);
231 stub.GetCode();
232 }
233 }
234
235
PrintBaseName(StringStream * stream)236 void StringAddStub::PrintBaseName(StringStream* stream) {
237 stream->Add("StringAddStub");
238 if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
239 stream->Add("_CheckBoth");
240 } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
241 stream->Add("_CheckLeft");
242 } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
243 stream->Add("_CheckRight");
244 }
245 if (pretenure_flag() == TENURED) {
246 stream->Add("_Tenured");
247 }
248 }
249
250
GetICState()251 InlineCacheState ICCompareStub::GetICState() {
252 CompareIC::State state = Max(left_, right_);
253 switch (state) {
254 case CompareIC::UNINITIALIZED:
255 return ::v8::internal::UNINITIALIZED;
256 case CompareIC::SMI:
257 case CompareIC::NUMBER:
258 case CompareIC::INTERNALIZED_STRING:
259 case CompareIC::STRING:
260 case CompareIC::UNIQUE_NAME:
261 case CompareIC::OBJECT:
262 case CompareIC::KNOWN_OBJECT:
263 return MONOMORPHIC;
264 case CompareIC::GENERIC:
265 return ::v8::internal::GENERIC;
266 }
267 UNREACHABLE();
268 return ::v8::internal::UNINITIALIZED;
269 }
270
271
AddToSpecialCache(Handle<Code> new_object)272 void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
273 ASSERT(*known_map_ != NULL);
274 Isolate* isolate = new_object->GetIsolate();
275 Factory* factory = isolate->factory();
276 return Map::UpdateCodeCache(known_map_,
277 strict() ?
278 factory->strict_compare_ic_string() :
279 factory->compare_ic_string(),
280 new_object);
281 }
282
283
FindCodeInSpecialCache(Code ** code_out)284 bool ICCompareStub::FindCodeInSpecialCache(Code** code_out) {
285 Factory* factory = isolate()->factory();
286 Code::Flags flags = Code::ComputeFlags(
287 GetCodeKind(),
288 UNINITIALIZED);
289 ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
290 Handle<Object> probe(
291 known_map_->FindInCodeCache(
292 strict() ?
293 *factory->strict_compare_ic_string() :
294 *factory->compare_ic_string(),
295 flags),
296 isolate());
297 if (probe->IsCode()) {
298 *code_out = Code::cast(*probe);
299 #ifdef DEBUG
300 Token::Value cached_op;
301 ICCompareStub::DecodeMinorKey((*code_out)->stub_info(), NULL, NULL, NULL,
302 &cached_op);
303 ASSERT(op_ == cached_op);
304 #endif
305 return true;
306 }
307 return false;
308 }
309
310
MinorKey()311 int ICCompareStub::MinorKey() {
312 return OpField::encode(op_ - Token::EQ) |
313 LeftStateField::encode(left_) |
314 RightStateField::encode(right_) |
315 HandlerStateField::encode(state_);
316 }
317
318
DecodeMinorKey(int minor_key,CompareIC::State * left_state,CompareIC::State * right_state,CompareIC::State * handler_state,Token::Value * op)319 void ICCompareStub::DecodeMinorKey(int minor_key,
320 CompareIC::State* left_state,
321 CompareIC::State* right_state,
322 CompareIC::State* handler_state,
323 Token::Value* op) {
324 if (left_state) {
325 *left_state =
326 static_cast<CompareIC::State>(LeftStateField::decode(minor_key));
327 }
328 if (right_state) {
329 *right_state =
330 static_cast<CompareIC::State>(RightStateField::decode(minor_key));
331 }
332 if (handler_state) {
333 *handler_state =
334 static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
335 }
336 if (op) {
337 *op = static_cast<Token::Value>(OpField::decode(minor_key) + Token::EQ);
338 }
339 }
340
341
Generate(MacroAssembler * masm)342 void ICCompareStub::Generate(MacroAssembler* masm) {
343 switch (state_) {
344 case CompareIC::UNINITIALIZED:
345 GenerateMiss(masm);
346 break;
347 case CompareIC::SMI:
348 GenerateSmis(masm);
349 break;
350 case CompareIC::NUMBER:
351 GenerateNumbers(masm);
352 break;
353 case CompareIC::STRING:
354 GenerateStrings(masm);
355 break;
356 case CompareIC::INTERNALIZED_STRING:
357 GenerateInternalizedStrings(masm);
358 break;
359 case CompareIC::UNIQUE_NAME:
360 GenerateUniqueNames(masm);
361 break;
362 case CompareIC::OBJECT:
363 GenerateObjects(masm);
364 break;
365 case CompareIC::KNOWN_OBJECT:
366 ASSERT(*known_map_ != NULL);
367 GenerateKnownObjects(masm);
368 break;
369 case CompareIC::GENERIC:
370 GenerateGeneric(masm);
371 break;
372 }
373 }
374
375
UpdateStatus(Handle<Object> object)376 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
377 ASSERT(!state_.Contains(GENERIC));
378 State old_state(state_);
379 if (object->IsNull()) {
380 state_.Add(NULL_TYPE);
381 } else if (object->IsUndefined()) {
382 state_.Add(UNDEFINED);
383 } else if (object->IsUndetectableObject() ||
384 object->IsOddball() ||
385 !object->IsHeapObject()) {
386 state_.RemoveAll();
387 state_.Add(GENERIC);
388 } else if (IsMonomorphic()) {
389 state_.RemoveAll();
390 state_.Add(GENERIC);
391 } else {
392 state_.Add(MONOMORPHIC_MAP);
393 }
394 TraceTransition(old_state, state_);
395 }
396
397
398 template<class StateType>
TraceTransition(StateType from,StateType to)399 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
400 // Note: Although a no-op transition is semantically OK, it is hinting at a
401 // bug somewhere in our state transition machinery.
402 ASSERT(from != to);
403 if (!FLAG_trace_ic) return;
404 char buffer[100];
405 NoAllocationStringAllocator allocator(buffer,
406 static_cast<unsigned>(sizeof(buffer)));
407 StringStream stream(&allocator);
408 stream.Add("[");
409 PrintBaseName(&stream);
410 stream.Add(": ");
411 from.Print(&stream);
412 stream.Add("=>");
413 to.Print(&stream);
414 stream.Add("]\n");
415 stream.OutputToStdOut();
416 }
417
418
PrintBaseName(StringStream * stream)419 void CompareNilICStub::PrintBaseName(StringStream* stream) {
420 CodeStub::PrintBaseName(stream);
421 stream->Add((nil_value_ == kNullValue) ? "(NullValue)":
422 "(UndefinedValue)");
423 }
424
425
PrintState(StringStream * stream)426 void CompareNilICStub::PrintState(StringStream* stream) {
427 state_.Print(stream);
428 }
429
430
Print(StringStream * stream) const431 void CompareNilICStub::State::Print(StringStream* stream) const {
432 stream->Add("(");
433 SimpleListPrinter printer(stream);
434 if (IsEmpty()) printer.Add("None");
435 if (Contains(UNDEFINED)) printer.Add("Undefined");
436 if (Contains(NULL_TYPE)) printer.Add("Null");
437 if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
438 if (Contains(GENERIC)) printer.Add("Generic");
439 stream->Add(")");
440 }
441
442
GetType(Zone * zone,Handle<Map> map)443 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
444 if (state_.Contains(CompareNilICStub::GENERIC)) {
445 return Type::Any(zone);
446 }
447
448 Type* result = Type::None(zone);
449 if (state_.Contains(CompareNilICStub::UNDEFINED)) {
450 result = Type::Union(result, Type::Undefined(zone), zone);
451 }
452 if (state_.Contains(CompareNilICStub::NULL_TYPE)) {
453 result = Type::Union(result, Type::Null(zone), zone);
454 }
455 if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
456 Type* type =
457 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
458 result = Type::Union(result, type, zone);
459 }
460
461 return result;
462 }
463
464
GetInputType(Zone * zone,Handle<Map> map)465 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
466 Type* output_type = GetType(zone, map);
467 Type* nil_type =
468 nil_value_ == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
469 return Type::Union(output_type, nil_type, zone);
470 }
471
472
PrintState(StringStream * stream)473 void CallIC_ArrayStub::PrintState(StringStream* stream) {
474 state_.Print(stream);
475 stream->Add(" (Array)");
476 }
477
478
PrintState(StringStream * stream)479 void CallICStub::PrintState(StringStream* stream) {
480 state_.Print(stream);
481 }
482
483
PrintName(StringStream * stream)484 void InstanceofStub::PrintName(StringStream* stream) {
485 const char* args = "";
486 if (HasArgsInRegisters()) {
487 args = "_REGS";
488 }
489
490 const char* inline_check = "";
491 if (HasCallSiteInlineCheck()) {
492 inline_check = "_INLINE";
493 }
494
495 const char* return_true_false_object = "";
496 if (ReturnTrueFalseObject()) {
497 return_true_false_object = "_TRUEFALSE";
498 }
499
500 stream->Add("InstanceofStub%s%s%s",
501 args,
502 inline_check,
503 return_true_false_object);
504 }
505
506
FinishCode(Handle<Code> code)507 void JSEntryStub::FinishCode(Handle<Code> code) {
508 Handle<FixedArray> handler_table =
509 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
510 handler_table->set(0, Smi::FromInt(handler_offset_));
511 code->set_handler_table(*handler_table);
512 }
513
514
Generate(MacroAssembler * masm)515 void KeyedLoadDictionaryElementPlatformStub::Generate(
516 MacroAssembler* masm) {
517 KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
518 }
519
520
GenerateAheadOfTime(Isolate * isolate)521 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
522 CreateAllocationSiteStub stub(isolate);
523 stub.GetCode();
524 }
525
526
Generate(MacroAssembler * masm)527 void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
528 switch (elements_kind_) {
529 case FAST_ELEMENTS:
530 case FAST_HOLEY_ELEMENTS:
531 case FAST_SMI_ELEMENTS:
532 case FAST_HOLEY_SMI_ELEMENTS:
533 case FAST_DOUBLE_ELEMENTS:
534 case FAST_HOLEY_DOUBLE_ELEMENTS:
535 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
536 case EXTERNAL_##TYPE##_ELEMENTS: \
537 case TYPE##_ELEMENTS:
538
539 TYPED_ARRAYS(TYPED_ARRAY_CASE)
540 #undef TYPED_ARRAY_CASE
541 UNREACHABLE();
542 break;
543 case DICTIONARY_ELEMENTS:
544 KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm);
545 break;
546 case SLOPPY_ARGUMENTS_ELEMENTS:
547 UNREACHABLE();
548 break;
549 }
550 }
551
552
PrintName(StringStream * stream)553 void ArgumentsAccessStub::PrintName(StringStream* stream) {
554 stream->Add("ArgumentsAccessStub_");
555 switch (type_) {
556 case READ_ELEMENT: stream->Add("ReadElement"); break;
557 case NEW_SLOPPY_FAST: stream->Add("NewSloppyFast"); break;
558 case NEW_SLOPPY_SLOW: stream->Add("NewSloppySlow"); break;
559 case NEW_STRICT: stream->Add("NewStrict"); break;
560 }
561 }
562
563
PrintName(StringStream * stream)564 void CallFunctionStub::PrintName(StringStream* stream) {
565 stream->Add("CallFunctionStub_Args%d", argc_);
566 }
567
568
PrintName(StringStream * stream)569 void CallConstructStub::PrintName(StringStream* stream) {
570 stream->Add("CallConstructStub");
571 if (RecordCallTarget()) stream->Add("_Recording");
572 }
573
574
PrintName(StringStream * stream)575 void ArrayConstructorStub::PrintName(StringStream* stream) {
576 stream->Add("ArrayConstructorStub");
577 switch (argument_count_) {
578 case ANY: stream->Add("_Any"); break;
579 case NONE: stream->Add("_None"); break;
580 case ONE: stream->Add("_One"); break;
581 case MORE_THAN_ONE: stream->Add("_More_Than_One"); break;
582 }
583 }
584
585
BasePrintName(const char * name,StringStream * stream)586 void ArrayConstructorStubBase::BasePrintName(const char* name,
587 StringStream* stream) {
588 stream->Add(name);
589 stream->Add("_");
590 stream->Add(ElementsKindToString(elements_kind()));
591 if (override_mode() == DISABLE_ALLOCATION_SITES) {
592 stream->Add("_DISABLE_ALLOCATION_SITES");
593 }
594 }
595
596
UpdateStatus(Handle<Object> object)597 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
598 Types old_types(types_);
599 bool to_boolean_value = types_.UpdateStatus(object);
600 TraceTransition(old_types, types_);
601 return to_boolean_value;
602 }
603
604
PrintState(StringStream * stream)605 void ToBooleanStub::PrintState(StringStream* stream) {
606 types_.Print(stream);
607 }
608
609
Print(StringStream * stream) const610 void ToBooleanStub::Types::Print(StringStream* stream) const {
611 stream->Add("(");
612 SimpleListPrinter printer(stream);
613 if (IsEmpty()) printer.Add("None");
614 if (Contains(UNDEFINED)) printer.Add("Undefined");
615 if (Contains(BOOLEAN)) printer.Add("Bool");
616 if (Contains(NULL_TYPE)) printer.Add("Null");
617 if (Contains(SMI)) printer.Add("Smi");
618 if (Contains(SPEC_OBJECT)) printer.Add("SpecObject");
619 if (Contains(STRING)) printer.Add("String");
620 if (Contains(SYMBOL)) printer.Add("Symbol");
621 if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
622 stream->Add(")");
623 }
624
625
UpdateStatus(Handle<Object> object)626 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
627 if (object->IsUndefined()) {
628 Add(UNDEFINED);
629 return false;
630 } else if (object->IsBoolean()) {
631 Add(BOOLEAN);
632 return object->IsTrue();
633 } else if (object->IsNull()) {
634 Add(NULL_TYPE);
635 return false;
636 } else if (object->IsSmi()) {
637 Add(SMI);
638 return Smi::cast(*object)->value() != 0;
639 } else if (object->IsSpecObject()) {
640 Add(SPEC_OBJECT);
641 return !object->IsUndetectableObject();
642 } else if (object->IsString()) {
643 Add(STRING);
644 return !object->IsUndetectableObject() &&
645 String::cast(*object)->length() != 0;
646 } else if (object->IsSymbol()) {
647 Add(SYMBOL);
648 return true;
649 } else if (object->IsHeapNumber()) {
650 ASSERT(!object->IsUndetectableObject());
651 Add(HEAP_NUMBER);
652 double value = HeapNumber::cast(*object)->value();
653 return value != 0 && !std::isnan(value);
654 } else {
655 // We should never see an internal object at runtime here!
656 UNREACHABLE();
657 return true;
658 }
659 }
660
661
NeedsMap() const662 bool ToBooleanStub::Types::NeedsMap() const {
663 return Contains(ToBooleanStub::SPEC_OBJECT)
664 || Contains(ToBooleanStub::STRING)
665 || Contains(ToBooleanStub::SYMBOL)
666 || Contains(ToBooleanStub::HEAP_NUMBER);
667 }
668
669
CanBeUndetectable() const670 bool ToBooleanStub::Types::CanBeUndetectable() const {
671 return Contains(ToBooleanStub::SPEC_OBJECT)
672 || Contains(ToBooleanStub::STRING);
673 }
674
675
GenerateAheadOfTime(Isolate * isolate)676 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
677 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
678 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
679 stub1.GetCode();
680 stub2.GetCode();
681 }
682
683
EntryHookTrampoline(intptr_t function,intptr_t stack_pointer,Isolate * isolate)684 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
685 intptr_t stack_pointer,
686 Isolate* isolate) {
687 FunctionEntryHook entry_hook = isolate->function_entry_hook();
688 ASSERT(entry_hook != NULL);
689 entry_hook(function, stack_pointer);
690 }
691
692
InstallDescriptor(Isolate * isolate,HydrogenCodeStub * stub)693 static void InstallDescriptor(Isolate* isolate, HydrogenCodeStub* stub) {
694 int major_key = stub->MajorKey();
695 CodeStubInterfaceDescriptor* descriptor =
696 isolate->code_stub_interface_descriptor(major_key);
697 if (!descriptor->initialized()) {
698 stub->InitializeInterfaceDescriptor(descriptor);
699 }
700 }
701
702
InstallDescriptors(Isolate * isolate)703 void ArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
704 ArrayNoArgumentConstructorStub stub1(isolate, GetInitialFastElementsKind());
705 InstallDescriptor(isolate, &stub1);
706 ArraySingleArgumentConstructorStub stub2(isolate,
707 GetInitialFastElementsKind());
708 InstallDescriptor(isolate, &stub2);
709 ArrayNArgumentsConstructorStub stub3(isolate, GetInitialFastElementsKind());
710 InstallDescriptor(isolate, &stub3);
711 }
712
713
InstallDescriptors(Isolate * isolate)714 void NumberToStringStub::InstallDescriptors(Isolate* isolate) {
715 NumberToStringStub stub(isolate);
716 InstallDescriptor(isolate, &stub);
717 }
718
719
InstallDescriptors(Isolate * isolate)720 void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
721 FastNewClosureStub stub(isolate, STRICT, false);
722 InstallDescriptor(isolate, &stub);
723 }
724
725
InstallDescriptors(Isolate * isolate)726 void FastNewContextStub::InstallDescriptors(Isolate* isolate) {
727 FastNewContextStub stub(isolate, FastNewContextStub::kMaximumSlots);
728 InstallDescriptor(isolate, &stub);
729 }
730
731
732 // static
InstallDescriptors(Isolate * isolate)733 void FastCloneShallowArrayStub::InstallDescriptors(Isolate* isolate) {
734 FastCloneShallowArrayStub stub(isolate, DONT_TRACK_ALLOCATION_SITE);
735 InstallDescriptor(isolate, &stub);
736 }
737
738
739 // static
InstallDescriptors(Isolate * isolate)740 void BinaryOpICStub::InstallDescriptors(Isolate* isolate) {
741 BinaryOpICStub stub(isolate, Token::ADD, NO_OVERWRITE);
742 InstallDescriptor(isolate, &stub);
743 }
744
745
746 // static
InstallDescriptors(Isolate * isolate)747 void BinaryOpWithAllocationSiteStub::InstallDescriptors(Isolate* isolate) {
748 BinaryOpWithAllocationSiteStub stub(isolate, Token::ADD, NO_OVERWRITE);
749 InstallDescriptor(isolate, &stub);
750 }
751
752
753 // static
InstallDescriptors(Isolate * isolate)754 void StringAddStub::InstallDescriptors(Isolate* isolate) {
755 StringAddStub stub(isolate, STRING_ADD_CHECK_NONE, NOT_TENURED);
756 InstallDescriptor(isolate, &stub);
757 }
758
759
760 // static
InstallDescriptors(Isolate * isolate)761 void RegExpConstructResultStub::InstallDescriptors(Isolate* isolate) {
762 RegExpConstructResultStub stub(isolate);
763 InstallDescriptor(isolate, &stub);
764 }
765
766
767 // static
InstallDescriptors(Isolate * isolate)768 void KeyedLoadGenericElementStub::InstallDescriptors(Isolate* isolate) {
769 KeyedLoadGenericElementStub stub(isolate);
770 InstallDescriptor(isolate, &stub);
771 }
772
773
ArrayConstructorStub(Isolate * isolate)774 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
775 : PlatformCodeStub(isolate), argument_count_(ANY) {
776 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
777 }
778
779
ArrayConstructorStub(Isolate * isolate,int argument_count)780 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
781 int argument_count)
782 : PlatformCodeStub(isolate) {
783 if (argument_count == 0) {
784 argument_count_ = NONE;
785 } else if (argument_count == 1) {
786 argument_count_ = ONE;
787 } else if (argument_count >= 2) {
788 argument_count_ = MORE_THAN_ONE;
789 } else {
790 UNREACHABLE();
791 }
792 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
793 }
794
795
InstallDescriptors(Isolate * isolate)796 void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
797 InternalArrayNoArgumentConstructorStub stub1(isolate, FAST_ELEMENTS);
798 InstallDescriptor(isolate, &stub1);
799 InternalArraySingleArgumentConstructorStub stub2(isolate, FAST_ELEMENTS);
800 InstallDescriptor(isolate, &stub2);
801 InternalArrayNArgumentsConstructorStub stub3(isolate, FAST_ELEMENTS);
802 InstallDescriptor(isolate, &stub3);
803 }
804
InternalArrayConstructorStub(Isolate * isolate)805 InternalArrayConstructorStub::InternalArrayConstructorStub(
806 Isolate* isolate) : PlatformCodeStub(isolate) {
807 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
808 }
809
810
811 } } // namespace v8::internal
812