blob: 5c9e1a2b8657cce26c13a4362ec04d1f4523da3c [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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/bootstrapper.h"
8#include "src/code-stubs.h"
9#include "src/cpu-profiler.h"
10#include "src/factory.h"
11#include "src/gdb-jit.h"
12#include "src/ic/handler-compiler.h"
13#include "src/ic/ic.h"
14#include "src/macro-assembler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000015
16namespace v8 {
17namespace internal {
18
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019
20CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
21 : call_descriptor_(stub->GetCallInterfaceDescriptor()),
22 stack_parameter_count_(no_reg),
23 hint_stack_parameter_count_(-1),
24 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
25 deoptimization_handler_(NULL),
26 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
27 miss_handler_(),
28 has_miss_handler_(false) {
29 stub->InitializeDescriptor(this);
30}
31
32
33CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
34 : stack_parameter_count_(no_reg),
35 hint_stack_parameter_count_(-1),
36 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
37 deoptimization_handler_(NULL),
38 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
39 miss_handler_(),
40 has_miss_handler_(false) {
41 CodeStub::InitializeDescriptor(isolate, stub_key, this);
42}
43
44
45void CodeStubDescriptor::Initialize(Address deoptimization_handler,
46 int hint_stack_parameter_count,
47 StubFunctionMode function_mode) {
48 deoptimization_handler_ = deoptimization_handler;
49 hint_stack_parameter_count_ = hint_stack_parameter_count;
50 function_mode_ = function_mode;
51}
52
53
54void CodeStubDescriptor::Initialize(Register stack_parameter_count,
55 Address deoptimization_handler,
56 int hint_stack_parameter_count,
57 StubFunctionMode function_mode,
58 HandlerArgumentsMode handler_mode) {
59 Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
60 stack_parameter_count_ = stack_parameter_count;
61 handler_arguments_mode_ = handler_mode;
62}
63
64
Leon Clarkee46be812010-01-19 14:06:41 +000065bool CodeStub::FindCodeInCache(Code** code_out) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
67 int index = stubs->FindEntry(GetKey());
Ben Murdochc7cc0282012-03-05 14:35:55 +000068 if (index != UnseededNumberDictionary::kNotFound) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 *code_out = Code::cast(stubs->ValueAt(index));
Leon Clarkee46be812010-01-19 14:06:41 +000070 return true;
Steve Blockd0582a62009-12-15 09:54:21 +000071 }
Leon Clarkee46be812010-01-19 14:06:41 +000072 return false;
73}
Steve Blockd0582a62009-12-15 09:54:21 +000074
Leon Clarkee46be812010-01-19 14:06:41 +000075
Ben Murdochb8a8cc12014-11-26 15:28:44 +000076void CodeStub::RecordCodeGeneration(Handle<Code> code) {
77 IC::RegisterWeakMapDependency(code);
78 OStringStream os;
79 os << *this;
80 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, os.c_str()));
81 Counters* counters = isolate()->counters();
Steve Block44f0eee2011-05-26 01:26:41 +010082 counters->total_stubs_code_size()->Increment(code->instruction_size());
Leon Clarkee46be812010-01-19 14:06:41 +000083}
84
85
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086Code::Kind CodeStub::GetCodeKind() const {
Steve Block6ded16b2010-05-10 14:33:55 +010087 return Code::STUB;
88}
89
90
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
92 Handle<Code> ic = GetCode();
93 ic = isolate()->factory()->CopyCode(ic);
94 ic->FindAndReplace(pattern);
95 RecordCodeGeneration(ic);
96 return ic;
97}
98
99
100Handle<Code> PlatformCodeStub::GenerateCode() {
101 Factory* factory = isolate()->factory();
102
103 // Generate the new code.
104 MacroAssembler masm(isolate(), NULL, 256);
105
106 // TODO(yangguo) remove this once the code serializer handles code stubs.
107 if (FLAG_serialize_toplevel) masm.enable_serializer();
108
109 {
110 // Update the static counter each time a new code stub is generated.
111 isolate()->counters()->code_stubs()->Increment();
112
113 // Generate the code for the stub.
114 masm.set_generating_stub(true);
115 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());
156 OStringStream name;
157 name << *this;
158 new_object->Disassemble(name.c_str(), os);
159 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
201void CodeStub::PrintBaseName(OStream& os) const { // NOLINT
202 os << MajorName(MajorKey(), false);
203}
204
205
206void CodeStub::PrintName(OStream& os) const { // NOLINT
207 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:
225 UNREACHABLE();
226 case NoCache:
227 *value_out = NULL;
228 break;
229 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000230}
231
232
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233static void InitializeDescriptorDispatchedCall(CodeStub* stub,
234 void** value_out) {
235 CodeStubDescriptor* descriptor_out =
236 reinterpret_cast<CodeStubDescriptor*>(value_out);
237 stub->InitializeDescriptor(descriptor_out);
238 descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100239}
240
241
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
243 CodeStubDescriptor* desc) {
244 void** value_out = reinterpret_cast<void**>(desc);
245 Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
246}
247
248
249void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
250 Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
251 // Code stubs with special cache cannot be recreated from stub key.
252 *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
253}
254
255
256MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
257 HandleScope scope(isolate);
258 Handle<Code> code;
259 void** value_out = reinterpret_cast<void**>(&code);
260 Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
261 return scope.CloseAndEscape(code);
262}
263
264
265// static
266void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
267 // Generate the uninitialized versions of the stub.
268 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
269 for (int mode = NO_OVERWRITE; mode <= OVERWRITE_RIGHT; ++mode) {
270 BinaryOpICStub stub(isolate,
271 static_cast<Token::Value>(op),
272 static_cast<OverwriteMode>(mode));
273 stub.GetCode();
274 }
275 }
276
277 // Generate special versions of the stub.
278 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
279}
280
281
282void BinaryOpICStub::PrintState(OStream& os) const { // NOLINT
283 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(
303 OStream& os) const { // NOLINT
304 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
318void StringAddStub::PrintBaseName(OStream& os) const { // NOLINT
319 os << "StringAddStub";
320 if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
321 os << "_CheckBoth";
322 } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
323 os << "_CheckLeft";
324 } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
325 os << "_CheckRight";
326 }
327 if (pretenure_flag() == TENURED) {
328 os << "_Tenured";
329 }
330}
331
332
333InlineCacheState CompareICStub::GetICState() const {
334 CompareICState::State state = Max(left(), right());
335 switch (state) {
336 case CompareICState::UNINITIALIZED:
337 return ::v8::internal::UNINITIALIZED;
338 case CompareICState::SMI:
339 case CompareICState::NUMBER:
340 case CompareICState::INTERNALIZED_STRING:
341 case CompareICState::STRING:
342 case CompareICState::UNIQUE_NAME:
343 case CompareICState::OBJECT:
344 case CompareICState::KNOWN_OBJECT:
345 return MONOMORPHIC;
346 case CompareICState::GENERIC:
347 return ::v8::internal::GENERIC;
348 }
349 UNREACHABLE();
350 return ::v8::internal::UNINITIALIZED;
351}
352
353
354Condition CompareICStub::GetCondition() const {
355 return CompareIC::ComputeCondition(op());
356}
357
358
359void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
360 DCHECK(*known_map_ != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100361 Isolate* isolate = new_object->GetIsolate();
362 Factory* factory = isolate->factory();
363 return Map::UpdateCodeCache(known_map_,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 strict() ?
365 factory->strict_compare_ic_string() :
366 factory->compare_ic_string(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100367 new_object);
368}
369
370
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
372 Factory* factory = isolate()->factory();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100373 Code::Flags flags = Code::ComputeFlags(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 GetCodeKind(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100375 UNINITIALIZED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000376 DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100377 Handle<Object> probe(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378 known_map_->FindInCodeCache(
379 strict() ?
380 *factory->strict_compare_ic_string() :
381 *factory->compare_ic_string(),
382 flags),
383 isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100384 if (probe->IsCode()) {
385 *code_out = Code::cast(*probe);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000386#ifdef DEBUG
387 CompareICStub decode((*code_out)->stub_key(), isolate());
388 DCHECK(op() == decode.op());
389 DCHECK(left() == decode.left());
390 DCHECK(right() == decode.right());
391 DCHECK(state() == decode.state());
392#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100393 return true;
394 }
395 return false;
396}
397
398
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399void CompareICStub::Generate(MacroAssembler* masm) {
400 switch (state()) {
401 case CompareICState::UNINITIALIZED:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100402 GenerateMiss(masm);
403 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000404 case CompareICState::SMI:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100405 GenerateSmis(masm);
406 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 case CompareICState::NUMBER:
408 GenerateNumbers(masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100409 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000410 case CompareICState::STRING:
Ben Murdoch257744e2011-11-30 15:57:28 +0000411 GenerateStrings(masm);
412 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 case CompareICState::INTERNALIZED_STRING:
414 GenerateInternalizedStrings(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000415 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416 case CompareICState::UNIQUE_NAME:
417 GenerateUniqueNames(masm);
418 break;
419 case CompareICState::OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100420 GenerateObjects(masm);
421 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 case CompareICState::KNOWN_OBJECT:
423 DCHECK(*known_map_ != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100424 GenerateKnownObjects(masm);
425 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 case CompareICState::GENERIC:
427 GenerateGeneric(masm);
428 break;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100429 }
430}
431
432
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433void CompareNilICStub::UpdateStatus(Handle<Object> object) {
434 State state = this->state();
435 DCHECK(!state.Contains(GENERIC));
436 State old_state = state;
437 if (object->IsNull()) {
438 state.Add(NULL_TYPE);
439 } else if (object->IsUndefined()) {
440 state.Add(UNDEFINED);
441 } else if (object->IsUndetectableObject() ||
442 object->IsOddball() ||
443 !object->IsHeapObject()) {
444 state.RemoveAll();
445 state.Add(GENERIC);
446 } else if (IsMonomorphic()) {
447 state.RemoveAll();
448 state.Add(GENERIC);
449 } else {
450 state.Add(MONOMORPHIC_MAP);
451 }
452 TraceTransition(old_state, state);
453 set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
454}
455
456
457template<class StateType>
458void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
459 // Note: Although a no-op transition is semantically OK, it is hinting at a
460 // bug somewhere in our state transition machinery.
461 DCHECK(from != to);
462 if (!FLAG_trace_ic) return;
463 OFStream os(stdout);
464 os << "[";
465 PrintBaseName(os);
466 os << ": " << from << "=>" << to << "]" << endl;
467}
468
469
470void CompareNilICStub::PrintBaseName(OStream& os) const { // NOLINT
471 CodeStub::PrintBaseName(os);
472 os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
473}
474
475
476void CompareNilICStub::PrintState(OStream& os) const { // NOLINT
477 os << state();
478}
479
480
481// TODO(svenpanne) Make this a real infix_ostream_iterator.
482class SimpleListPrinter {
483 public:
484 explicit SimpleListPrinter(OStream& os) : os_(os), first_(true) {}
485
486 void Add(const char* s) {
487 if (first_) {
488 first_ = false;
489 } else {
490 os_ << ",";
491 }
492 os_ << s;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100493 }
494
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 private:
496 OStream& os_;
497 bool first_;
498};
499
500
501OStream& operator<<(OStream& os, const CompareNilICStub::State& s) {
502 os << "(";
503 SimpleListPrinter p(os);
504 if (s.IsEmpty()) p.Add("None");
505 if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
506 if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
507 if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
508 if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
509 return os << ")";
510}
511
512
513Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
514 State state = this->state();
515 if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
516
517 Type* result = Type::None(zone);
518 if (state.Contains(CompareNilICStub::UNDEFINED)) {
519 result = Type::Union(result, Type::Undefined(zone), zone);
520 }
521 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
522 result = Type::Union(result, Type::Null(zone), zone);
523 }
524 if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
525 Type* type =
526 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
527 result = Type::Union(result, type, zone);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100528 }
529
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 return result;
531}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100532
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533
534Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
535 Type* output_type = GetType(zone, map);
536 Type* nil_type =
537 nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
538 return Type::Union(output_type, nil_type, zone);
539}
540
541
542void CallIC_ArrayStub::PrintState(OStream& os) const { // NOLINT
543 os << state() << " (Array)";
544}
545
546
547void CallICStub::PrintState(OStream& os) const { // NOLINT
548 os << state();
549}
550
551
552void InstanceofStub::PrintName(OStream& os) const { // NOLINT
553 os << "InstanceofStub";
554 if (HasArgsInRegisters()) os << "_REGS";
555 if (HasCallSiteInlineCheck()) os << "_INLINE";
556 if (ReturnTrueFalseObject()) os << "_TRUEFALSE";
Ben Murdoch086aeea2011-05-13 15:57:08 +0100557}
558
559
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100560void JSEntryStub::FinishCode(Handle<Code> code) {
561 Handle<FixedArray> handler_table =
562 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
563 handler_table->set(0, Smi::FromInt(handler_offset_));
564 code->set_handler_table(*handler_table);
565}
566
567
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568void LoadFastElementStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
569 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
570}
571
572
573void LoadDictionaryElementStub::InitializeDescriptor(
574 CodeStubDescriptor* descriptor) {
575 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
576}
577
578
579void KeyedLoadGenericStub::InitializeDescriptor(
580 CodeStubDescriptor* descriptor) {
581 descriptor->Initialize(
582 Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
583}
584
585
586void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
587 if (kind() == Code::STORE_IC) {
588 descriptor->Initialize(FUNCTION_ADDR(StoreIC_MissFromStubFailure));
589 } else if (kind() == Code::KEYED_LOAD_IC) {
590 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
591 }
592}
593
594
595CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
596 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
597 return LoadDescriptor(isolate());
598 } else {
599 DCHECK_EQ(Code::STORE_IC, kind());
600 return StoreDescriptor(isolate());
601 }
602}
603
604
605void StoreFastElementStub::InitializeDescriptor(
606 CodeStubDescriptor* descriptor) {
607 descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
608}
609
610
611void ElementsTransitionAndStoreStub::InitializeDescriptor(
612 CodeStubDescriptor* descriptor) {
613 descriptor->Initialize(FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss));
614}
615
616
617static void InitializeVectorLoadStub(Isolate* isolate,
618 CodeStubDescriptor* descriptor,
619 Address deoptimization_handler) {
620 DCHECK(FLAG_vector_ics);
621 descriptor->Initialize(deoptimization_handler);
622}
623
624
625void VectorLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
626 InitializeVectorLoadStub(isolate(), descriptor,
627 FUNCTION_ADDR(VectorLoadIC_MissFromStubFailure));
628}
629
630
631void VectorKeyedLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
632 InitializeVectorLoadStub(
633 isolate(), descriptor,
634 FUNCTION_ADDR(VectorKeyedLoadIC_MissFromStubFailure));
635}
636
637
638void MegamorphicLoadStub::InitializeDescriptor(CodeStubDescriptor* d) {}
639
640
641void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
642 descriptor->Initialize(
643 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
644}
645
646
647void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
648
649
650void ToNumberStub::InitializeDescriptor(CodeStubDescriptor* d) {}
651
652
653void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
654 NumberToStringDescriptor call_descriptor(isolate());
655 descriptor->Initialize(
656 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
657}
658
659
660void FastCloneShallowArrayStub::InitializeDescriptor(
661 CodeStubDescriptor* descriptor) {
662 FastCloneShallowArrayDescriptor call_descriptor(isolate());
663 descriptor->Initialize(
664 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
665}
666
667
668void FastCloneShallowObjectStub::InitializeDescriptor(
669 CodeStubDescriptor* descriptor) {
670 FastCloneShallowObjectDescriptor call_descriptor(isolate());
671 descriptor->Initialize(
672 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
673}
674
675
676void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
677
678
679void RegExpConstructResultStub::InitializeDescriptor(
680 CodeStubDescriptor* descriptor) {
681 descriptor->Initialize(
682 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
683}
684
685
686void TransitionElementsKindStub::InitializeDescriptor(
687 CodeStubDescriptor* descriptor) {
688 descriptor->Initialize(
689 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
690}
691
692
693void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
694 descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
695 descriptor->SetMissHandler(
696 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
697}
698
699
700void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
701 descriptor->Initialize(FUNCTION_ADDR(ToBooleanIC_Miss));
702 descriptor->SetMissHandler(
703 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
704}
705
706
707void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
708 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_Miss));
709 descriptor->SetMissHandler(
710 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
711}
712
713
714void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
715 CodeStubDescriptor* descriptor) {
716 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
717}
718
719
720void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
721 descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
722}
723
724
725void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
726 CreateAllocationSiteStub stub(isolate);
727 stub.GetCode();
728}
729
730
731void StoreElementStub::Generate(MacroAssembler* masm) {
732 switch (elements_kind()) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000733 case FAST_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000734 case FAST_HOLEY_ELEMENTS:
735 case FAST_SMI_ELEMENTS:
736 case FAST_HOLEY_SMI_ELEMENTS:
Ben Murdoch589d6972011-11-30 16:04:58 +0000737 case FAST_DOUBLE_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000738 case FAST_HOLEY_DOUBLE_ELEMENTS:
739#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
740 case EXTERNAL_##TYPE##_ELEMENTS: \
741 case TYPE##_ELEMENTS:
742
743 TYPED_ARRAYS(TYPED_ARRAY_CASE)
744#undef TYPED_ARRAY_CASE
745 UNREACHABLE();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000746 break;
Ben Murdoch589d6972011-11-30 16:04:58 +0000747 case DICTIONARY_ELEMENTS:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 ElementHandlerCompiler::GenerateStoreSlow(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000749 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000750 case SLOPPY_ARGUMENTS_ELEMENTS:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000751 UNREACHABLE();
752 break;
753 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000754}
755
756
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
758 switch (type()) {
759 case READ_ELEMENT:
760 GenerateReadElement(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000761 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000762 case NEW_SLOPPY_FAST:
763 GenerateNewSloppyFast(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000764 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765 case NEW_SLOPPY_SLOW:
766 GenerateNewSloppySlow(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000767 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000768 case NEW_STRICT:
769 GenerateNewStrict(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000770 break;
771 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000772}
773
774
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775void ArgumentsAccessStub::PrintName(OStream& os) const { // NOLINT
776 os << "ArgumentsAccessStub_";
777 switch (type()) {
778 case READ_ELEMENT:
779 os << "ReadElement";
780 break;
781 case NEW_SLOPPY_FAST:
782 os << "NewSloppyFast";
783 break;
784 case NEW_SLOPPY_SLOW:
785 os << "NewSloppySlow";
786 break;
787 case NEW_STRICT:
788 os << "NewStrict";
789 break;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000790 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000791 return;
Ben Murdoch257744e2011-11-30 15:57:28 +0000792}
793
794
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000795void CallFunctionStub::PrintName(OStream& os) const { // NOLINT
796 os << "CallFunctionStub_Args" << argc();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100797}
798
799
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800void CallConstructStub::PrintName(OStream& os) const { // NOLINT
801 os << "CallConstructStub";
802 if (RecordCallTarget()) os << "_Recording";
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100803}
804
805
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806void ArrayConstructorStub::PrintName(OStream& os) const { // NOLINT
807 os << "ArrayConstructorStub";
808 switch (argument_count()) {
809 case ANY:
810 os << "_Any";
811 break;
812 case NONE:
813 os << "_None";
814 break;
815 case ONE:
816 os << "_One";
817 break;
818 case MORE_THAN_ONE:
819 os << "_More_Than_One";
820 break;
821 }
822 return;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000823}
824
825
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000826OStream& ArrayConstructorStubBase::BasePrintName(OStream& os, // NOLINT
827 const char* name) const {
828 os << name << "_" << ElementsKindToString(elements_kind());
829 if (override_mode() == DISABLE_ALLOCATION_SITES) {
830 os << "_DISABLE_ALLOCATION_SITES";
831 }
832 return os;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000833}
834
835
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
837 Types new_types = types();
838 Types old_types = new_types;
839 bool to_boolean_value = new_types.UpdateStatus(object);
840 TraceTransition(old_types, new_types);
841 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToByte()));
842 return to_boolean_value;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000843}
844
845
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846void ToBooleanStub::PrintState(OStream& os) const { // NOLINT
847 os << types();
848}
849
850
851OStream& operator<<(OStream& os, const ToBooleanStub::Types& s) {
852 os << "(";
853 SimpleListPrinter p(os);
854 if (s.IsEmpty()) p.Add("None");
855 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
856 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
857 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
858 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
859 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
860 if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
861 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
862 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
863 return os << ")";
864}
865
866
867bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000868 if (object->IsUndefined()) {
869 Add(UNDEFINED);
870 return false;
871 } else if (object->IsBoolean()) {
872 Add(BOOLEAN);
873 return object->IsTrue();
874 } else if (object->IsNull()) {
875 Add(NULL_TYPE);
876 return false;
877 } else if (object->IsSmi()) {
878 Add(SMI);
879 return Smi::cast(*object)->value() != 0;
880 } else if (object->IsSpecObject()) {
881 Add(SPEC_OBJECT);
882 return !object->IsUndetectableObject();
883 } else if (object->IsString()) {
884 Add(STRING);
885 return !object->IsUndetectableObject() &&
886 String::cast(*object)->length() != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 } else if (object->IsSymbol()) {
888 Add(SYMBOL);
889 return true;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000890 } else if (object->IsHeapNumber()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 DCHECK(!object->IsUndetectableObject());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000892 Add(HEAP_NUMBER);
893 double value = HeapNumber::cast(*object)->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894 return value != 0 && !std::isnan(value);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000895 } else {
896 // We should never see an internal object at runtime here!
897 UNREACHABLE();
898 return true;
899 }
900}
901
902
903bool ToBooleanStub::Types::NeedsMap() const {
904 return Contains(ToBooleanStub::SPEC_OBJECT)
905 || Contains(ToBooleanStub::STRING)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 || Contains(ToBooleanStub::SYMBOL)
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000907 || Contains(ToBooleanStub::HEAP_NUMBER);
908}
909
910
911bool ToBooleanStub::Types::CanBeUndetectable() const {
912 return Contains(ToBooleanStub::SPEC_OBJECT)
913 || Contains(ToBooleanStub::STRING);
914}
915
916
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
918 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
919 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
920 stub1.GetCode();
921 stub2.GetCode();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100922}
923
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924
925void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
926 intptr_t stack_pointer,
927 Isolate* isolate) {
928 FunctionEntryHook entry_hook = isolate->function_entry_hook();
929 DCHECK(entry_hook != NULL);
930 entry_hook(function, stack_pointer);
931}
932
933
934ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
935 : PlatformCodeStub(isolate) {
936 minor_key_ = ArgumentCountBits::encode(ANY);
937 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
938}
939
940
941ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
942 int argument_count)
943 : PlatformCodeStub(isolate) {
944 if (argument_count == 0) {
945 minor_key_ = ArgumentCountBits::encode(NONE);
946 } else if (argument_count == 1) {
947 minor_key_ = ArgumentCountBits::encode(ONE);
948 } else if (argument_count >= 2) {
949 minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
950 } else {
951 UNREACHABLE();
952 }
953 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
954}
955
956
957InternalArrayConstructorStub::InternalArrayConstructorStub(
958 Isolate* isolate) : PlatformCodeStub(isolate) {
959 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
960}
961
962
Steve Blocka7e24c12009-10-30 11:49:00 +0000963} } // namespace v8::internal