blob: 2d94ec978e098da76d89aedb2b41c48d1d5b2d5d [file] [log] [blame]
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "bootstrapper.h"
31#include "code-stubs.h"
ager@chromium.orgea91cc52011-05-23 06:06:11 +000032#include "stub-cache.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033#include "factory.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000034#include "gdb-jit.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035#include "macro-assembler.h"
36
kasperl@chromium.org71affb52009-05-26 05:44:31 +000037namespace v8 {
38namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000040
41CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
42 : register_param_count_(-1),
43 stack_parameter_count_(NULL),
danno@chromium.orgca29dd82013-04-26 11:59:48 +000044 hint_stack_parameter_count_(-1),
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000045 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
46 register_params_(NULL),
47 deoptimization_handler_(NULL),
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000048 miss_handler_(IC_Utility(IC::kUnreachable), Isolate::Current()),
49 has_miss_handler_(false) { }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000050
51
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000052bool CodeStub::FindCodeInCache(Code** code_out, Isolate* isolate) {
53 UnseededNumberDictionary* stubs = isolate->heap()->code_stubs();
54 int index = stubs->FindEntry(GetKey());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000055 if (index != UnseededNumberDictionary::kNotFound) {
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000056 *code_out = Code::cast(stubs->ValueAt(index));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000057 return true;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000058 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000059 return false;
60}
ager@chromium.orgc4c92722009-11-18 14:12:51 +000061
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000062
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000063SmartArrayPointer<const char> CodeStub::GetName() {
whesse@chromium.org030d38e2011-07-13 13:23:34 +000064 char buffer[100];
65 NoAllocationStringAllocator allocator(buffer,
66 static_cast<unsigned>(sizeof(buffer)));
67 StringStream stream(&allocator);
68 PrintName(&stream);
69 return stream.ToCString();
70}
71
72
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000073void CodeStub::RecordCodeGeneration(Code* code, Isolate* isolate) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000074 SmartArrayPointer<const char> name = GetName();
whesse@chromium.org030d38e2011-07-13 13:23:34 +000075 PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, *name));
76 GDBJIT(AddCode(GDBJITInterface::STUB, *name, code));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000077 Counters* counters = isolate->counters();
78 counters->total_stubs_code_size()->Increment(code->instruction_size());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000079}
80
81
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +000082Code::Kind CodeStub::GetCodeKind() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000083 return Code::STUB;
84}
85
86
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000087Handle<Code> PlatformCodeStub::GenerateCode() {
88 Isolate* isolate = Isolate::Current();
89 Factory* factory = isolate->factory();
90
91 // Generate the new code.
92 MacroAssembler masm(isolate, NULL, 256);
93
94 {
95 // Update the static counter each time a new code stub is generated.
96 isolate->counters()->code_stubs()->Increment();
97
98 // Nested stubs are not allowed for leaves.
99 AllowStubCallsScope allow_scope(&masm, false);
100
101 // Generate the code for the stub.
102 masm.set_generating_stub(true);
103 NoCurrentFrameScope scope(&masm);
104 Generate(&masm);
105 }
106
107 // Create the code object.
108 CodeDesc desc;
109 masm.GetCode(&desc);
110
111 // Copy the generated code into a heap object.
112 Code::Flags flags = Code::ComputeFlags(
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000113 GetCodeKind(),
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000114 GetICState(),
115 GetExtraICState(),
ulan@chromium.org750145a2013-03-07 15:14:13 +0000116 GetStubType(),
117 GetStubFlags());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000118 Handle<Code> new_object = factory->NewCode(
119 desc, flags, masm.CodeObject(), NeedsImmovableCode());
120 return new_object;
121}
122
123
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000124Handle<Code> CodeStub::GetCode(Isolate* isolate) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000125 Factory* factory = isolate->factory();
126 Heap* heap = isolate->heap();
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000127 Code* code;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000128 if (UseSpecialCache()
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000129 ? FindCodeInSpecialCache(&code, isolate)
130 : FindCodeInCache(&code, isolate)) {
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000131 ASSERT(IsPregenerated() == code->is_pregenerated());
132 return Handle<Code>(code);
133 }
134
135 {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000136 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000137
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000138 Handle<Code> new_object = GenerateCode();
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000139 new_object->set_major_key(MajorKey());
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000140 FinishCode(new_object);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000141 RecordCodeGeneration(*new_object, isolate);
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000142
143#ifdef ENABLE_DISASSEMBLER
144 if (FLAG_print_code_stubs) {
145 new_object->Disassemble(*GetName());
146 PrintF("\n");
147 }
148#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000150 if (UseSpecialCache()) {
151 AddToSpecialCache(new_object);
152 } else {
153 // Update the dictionary and the root in Heap.
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000154 Handle<UnseededNumberDictionary> dict =
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000155 factory->DictionaryAtNumberPut(
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000156 Handle<UnseededNumberDictionary>(heap->code_stubs()),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000157 GetKey(),
158 new_object);
159 heap->public_set_code_stubs(*dict);
160 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000161 code = *new_object;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000163
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000164 Activate(code);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000165 ASSERT(!NeedsImmovableCode() ||
166 heap->lo_space()->Contains(code) ||
167 heap->code_space()->FirstPage()->Contains(code->address()));
lrn@chromium.org7516f052011-03-30 08:52:27 +0000168 return Handle<Code>(code, isolate);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000169}
170
171
ager@chromium.org5c838252010-02-19 08:53:10 +0000172const char* CodeStub::MajorName(CodeStub::Major major_key,
173 bool allow_unknown_keys) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174 switch (major_key) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000175#define DEF_CASE(name) case name: return #name "Stub";
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000176 CODE_STUB_LIST(DEF_CASE)
ager@chromium.org3811b432009-10-28 14:53:37 +0000177#undef DEF_CASE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178 default:
ager@chromium.org5c838252010-02-19 08:53:10 +0000179 if (!allow_unknown_keys) {
180 UNREACHABLE();
181 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 return NULL;
183 }
184}
185
186
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000187void CodeStub::PrintName(StringStream* stream) {
188 stream->Add("%s", MajorName(MajorKey(), false));
189}
190
191
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000192void BinaryOpStub::Generate(MacroAssembler* masm) {
193 // Explicitly allow generation of nested stubs. It is safe here because
194 // generation code does not use any raw pointers.
195 AllowStubCallsScope allow_stub_calls(masm, true);
196
197 BinaryOpIC::TypeInfo operands_type = Max(left_type_, right_type_);
198 if (left_type_ == BinaryOpIC::ODDBALL && right_type_ == BinaryOpIC::ODDBALL) {
199 // The OddballStub handles a number and an oddball, not two oddballs.
200 operands_type = BinaryOpIC::GENERIC;
201 }
202 switch (operands_type) {
203 case BinaryOpIC::UNINITIALIZED:
204 GenerateTypeTransition(masm);
205 break;
206 case BinaryOpIC::SMI:
207 GenerateSmiStub(masm);
208 break;
209 case BinaryOpIC::INT32:
210 GenerateInt32Stub(masm);
211 break;
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000212 case BinaryOpIC::NUMBER:
213 GenerateNumberStub(masm);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000214 break;
215 case BinaryOpIC::ODDBALL:
216 GenerateOddballStub(masm);
217 break;
218 case BinaryOpIC::STRING:
219 GenerateStringStub(masm);
220 break;
221 case BinaryOpIC::GENERIC:
222 GenerateGeneric(masm);
223 break;
224 default:
225 UNREACHABLE();
226 }
227}
228
229
230#define __ ACCESS_MASM(masm)
231
232
233void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
234 switch (op_) {
235 case Token::ADD:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000236 __ InvokeBuiltin(Builtins::ADD, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000237 break;
238 case Token::SUB:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000239 __ InvokeBuiltin(Builtins::SUB, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000240 break;
241 case Token::MUL:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000242 __ InvokeBuiltin(Builtins::MUL, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000243 break;
244 case Token::DIV:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000245 __ InvokeBuiltin(Builtins::DIV, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000246 break;
247 case Token::MOD:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000248 __ InvokeBuiltin(Builtins::MOD, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000249 break;
250 case Token::BIT_OR:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000251 __ InvokeBuiltin(Builtins::BIT_OR, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000252 break;
253 case Token::BIT_AND:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000254 __ InvokeBuiltin(Builtins::BIT_AND, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000255 break;
256 case Token::BIT_XOR:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000257 __ InvokeBuiltin(Builtins::BIT_XOR, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000258 break;
259 case Token::SAR:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000260 __ InvokeBuiltin(Builtins::SAR, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000261 break;
262 case Token::SHR:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000263 __ InvokeBuiltin(Builtins::SHR, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000264 break;
265 case Token::SHL:
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000266 __ InvokeBuiltin(Builtins::SHL, CALL_FUNCTION);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000267 break;
268 default:
269 UNREACHABLE();
270 }
271}
272
273
274#undef __
275
276
277void BinaryOpStub::PrintName(StringStream* stream) {
278 const char* op_name = Token::Name(op_);
279 const char* overwrite_name;
280 switch (mode_) {
281 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
282 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
283 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
284 default: overwrite_name = "UnknownOverwrite"; break;
285 }
286 stream->Add("BinaryOpStub_%s_%s_%s+%s",
287 op_name,
288 overwrite_name,
289 BinaryOpIC::GetName(left_type_),
290 BinaryOpIC::GetName(right_type_));
291}
292
293
294void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
295 ASSERT(left_type_ == BinaryOpIC::STRING || right_type_ == BinaryOpIC::STRING);
296 ASSERT(op_ == Token::ADD);
297 if (left_type_ == BinaryOpIC::STRING && right_type_ == BinaryOpIC::STRING) {
298 GenerateBothStringStub(masm);
299 return;
300 }
301 // Try to add arguments as strings, otherwise, transition to the generic
302 // BinaryOpIC type.
303 GenerateAddStrings(masm);
304 GenerateTypeTransition(masm);
305}
306
307
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000308InlineCacheState ICCompareStub::GetICState() {
309 CompareIC::State state = Max(left_, right_);
310 switch (state) {
311 case CompareIC::UNINITIALIZED:
312 return ::v8::internal::UNINITIALIZED;
313 case CompareIC::SMI:
314 case CompareIC::NUMBER:
315 case CompareIC::INTERNALIZED_STRING:
316 case CompareIC::STRING:
317 case CompareIC::UNIQUE_NAME:
318 case CompareIC::OBJECT:
319 case CompareIC::KNOWN_OBJECT:
320 return MONOMORPHIC;
321 case CompareIC::GENERIC:
322 return ::v8::internal::GENERIC;
323 }
324 UNREACHABLE();
325 return ::v8::internal::UNINITIALIZED;
326}
327
328
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000329void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
330 ASSERT(*known_map_ != NULL);
331 Isolate* isolate = new_object->GetIsolate();
332 Factory* factory = isolate->factory();
333 return Map::UpdateCodeCache(known_map_,
verwaest@chromium.orgde64f722012-08-16 15:44:54 +0000334 strict() ?
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000335 factory->strict_compare_ic_string() :
336 factory->compare_ic_string(),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000337 new_object);
338}
339
340
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000341bool ICCompareStub::FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000342 Factory* factory = isolate->factory();
343 Code::Flags flags = Code::ComputeFlags(
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000344 GetCodeKind(),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000345 UNINITIALIZED);
verwaest@chromium.orgde64f722012-08-16 15:44:54 +0000346 ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000347 Handle<Object> probe(
348 known_map_->FindInCodeCache(
349 strict() ?
350 *factory->strict_compare_ic_string() :
351 *factory->compare_ic_string(),
352 flags),
353 isolate);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000354 if (probe->IsCode()) {
355 *code_out = Code::cast(*probe);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000356#ifdef DEBUG
357 Token::Value cached_op;
358 ICCompareStub::DecodeMinorKey((*code_out)->stub_info(), NULL, NULL, NULL,
359 &cached_op);
360 ASSERT(op_ == cached_op);
361#endif
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000362 return true;
363 }
364 return false;
365}
366
367
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000368int ICCompareStub::MinorKey() {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000369 return OpField::encode(op_ - Token::EQ) |
370 LeftStateField::encode(left_) |
371 RightStateField::encode(right_) |
372 HandlerStateField::encode(state_);
373}
374
375
376void ICCompareStub::DecodeMinorKey(int minor_key,
377 CompareIC::State* left_state,
378 CompareIC::State* right_state,
379 CompareIC::State* handler_state,
380 Token::Value* op) {
381 if (left_state) {
382 *left_state =
383 static_cast<CompareIC::State>(LeftStateField::decode(minor_key));
384 }
385 if (right_state) {
386 *right_state =
387 static_cast<CompareIC::State>(RightStateField::decode(minor_key));
388 }
389 if (handler_state) {
390 *handler_state =
391 static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
392 }
393 if (op) {
394 *op = static_cast<Token::Value>(OpField::decode(minor_key) + Token::EQ);
395 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000396}
397
398
399void ICCompareStub::Generate(MacroAssembler* masm) {
400 switch (state_) {
401 case CompareIC::UNINITIALIZED:
402 GenerateMiss(masm);
403 break;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000404 case CompareIC::SMI:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000405 GenerateSmis(masm);
406 break;
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000407 case CompareIC::NUMBER:
408 GenerateNumbers(masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000409 break;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000410 case CompareIC::STRING:
lrn@chromium.org1c092762011-05-09 09:42:16 +0000411 GenerateStrings(masm);
412 break;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000413 case CompareIC::INTERNALIZED_STRING:
414 GenerateInternalizedStrings(masm);
415 break;
416 case CompareIC::UNIQUE_NAME:
417 GenerateUniqueNames(masm);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000418 break;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000419 case CompareIC::OBJECT:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000420 GenerateObjects(masm);
421 break;
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000422 case CompareIC::KNOWN_OBJECT:
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000423 ASSERT(*known_map_ != NULL);
424 GenerateKnownObjects(masm);
425 break;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000426 case CompareIC::GENERIC:
427 GenerateGeneric(masm);
428 break;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000429 }
430}
431
432
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000433void CompareNilICStub::Record(Handle<Object> object) {
danno@chromium.org41728482013-06-12 22:31:22 +0000434 ASSERT(state_ != State::Generic());
ulan@chromium.org837a67e2013-06-11 15:39:48 +0000435 if (object->IsNull()) {
danno@chromium.org41728482013-06-12 22:31:22 +0000436 state_.Add(NULL_TYPE);
ulan@chromium.org837a67e2013-06-11 15:39:48 +0000437 } else if (object->IsUndefined()) {
danno@chromium.org41728482013-06-12 22:31:22 +0000438 state_.Add(UNDEFINED);
ulan@chromium.org837a67e2013-06-11 15:39:48 +0000439 } else if (object->IsUndetectableObject() ||
440 object->IsOddball() ||
441 !object->IsHeapObject()) {
danno@chromium.org41728482013-06-12 22:31:22 +0000442 state_ = State::Generic();
ulan@chromium.org837a67e2013-06-11 15:39:48 +0000443 } else if (IsMonomorphic()) {
danno@chromium.org41728482013-06-12 22:31:22 +0000444 state_ = State::Generic();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000445 } else {
danno@chromium.org41728482013-06-12 22:31:22 +0000446 state_.Add(MONOMORPHIC_MAP);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000447 }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000448}
449
450
danno@chromium.org41728482013-06-12 22:31:22 +0000451void CompareNilICStub::State::TraceTransition(State to) const {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000452 #ifdef DEBUG
453 if (!FLAG_trace_ic) return;
454 char buffer[100];
455 NoAllocationStringAllocator allocator(buffer,
456 static_cast<unsigned>(sizeof(buffer)));
457 StringStream stream(&allocator);
458 stream.Add("[CompareNilIC : ");
459 Print(&stream);
460 stream.Add("=>");
461 to.Print(&stream);
462 stream.Add("]\n");
463 stream.OutputToStdOut();
464 #endif
465}
466
467
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000468void CompareNilICStub::PrintName(StringStream* stream) {
469 stream->Add("CompareNilICStub_");
danno@chromium.org41728482013-06-12 22:31:22 +0000470 state_.Print(stream);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000471 stream->Add((nil_value_ == kNullValue) ? "(NullValue|":
472 "(UndefinedValue|");
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000473}
474
475
danno@chromium.org41728482013-06-12 22:31:22 +0000476void CompareNilICStub::State::Print(StringStream* stream) const {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000477 stream->Add("(");
478 SimpleListPrinter printer(stream);
479 if (IsEmpty()) printer.Add("None");
480 if (Contains(UNDEFINED)) printer.Add("Undefined");
481 if (Contains(NULL_TYPE)) printer.Add("Null");
482 if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
483 if (Contains(UNDETECTABLE)) printer.Add("Undetectable");
danno@chromium.org41728482013-06-12 22:31:22 +0000484 if (Contains(GENERIC)) printer.Add("Generic");
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000485 stream->Add(")");
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000486}
487
488
danno@chromium.org41728482013-06-12 22:31:22 +0000489Handle<Type> CompareNilICStub::StateToType(
490 Isolate* isolate,
491 State state,
492 Handle<Map> map) {
493 if (state.Contains(CompareNilICStub::GENERIC)) {
494 return handle(Type::Any(), isolate);
495 }
496
497 Handle<Type> result(Type::None(), isolate);
498 if (state.Contains(CompareNilICStub::UNDEFINED)) {
499 result = handle(Type::Union(result, handle(Type::Undefined(), isolate)),
500 isolate);
501 }
502 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
503 result = handle(Type::Union(result, handle(Type::Null(), isolate)),
504 isolate);
505 }
506 if (state.Contains(CompareNilICStub::UNDETECTABLE)) {
507 result = handle(Type::Union(result, handle(Type::Undetectable(), isolate)),
508 isolate);
509 } else if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
510 Type* type = map.is_null() ? Type::Detectable() : Type::Class(map);
511 result = handle(Type::Union(result, handle(type, isolate)), isolate);
512 }
513
514 return result;
515}
516
517
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000518void InstanceofStub::PrintName(StringStream* stream) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000519 const char* args = "";
520 if (HasArgsInRegisters()) {
521 args = "_REGS";
522 }
523
524 const char* inline_check = "";
525 if (HasCallSiteInlineCheck()) {
526 inline_check = "_INLINE";
527 }
528
529 const char* return_true_false_object = "";
530 if (ReturnTrueFalseObject()) {
531 return_true_false_object = "_TRUEFALSE";
532 }
533
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000534 stream->Add("InstanceofStub%s%s%s",
535 args,
536 inline_check,
537 return_true_false_object);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000538}
539
540
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000541void JSEntryStub::FinishCode(Handle<Code> code) {
542 Handle<FixedArray> handler_table =
543 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
544 handler_table->set(0, Smi::FromInt(handler_offset_));
545 code->set_handler_table(*handler_table);
546}
547
548
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000549void KeyedLoadDictionaryElementStub::Generate(MacroAssembler* masm) {
550 KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000551}
552
553
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000554void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
555 switch (elements_kind_) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000556 case FAST_ELEMENTS:
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000557 case FAST_HOLEY_ELEMENTS:
558 case FAST_SMI_ELEMENTS:
559 case FAST_HOLEY_SMI_ELEMENTS: {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000560 KeyedStoreStubCompiler::GenerateStoreFastElement(masm,
561 is_js_array_,
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000562 elements_kind_,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000563 store_mode_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000564 }
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000565 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000566 case FAST_DOUBLE_ELEMENTS:
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000567 case FAST_HOLEY_DOUBLE_ELEMENTS:
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000568 KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000569 is_js_array_,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000570 store_mode_);
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000571 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000572 case EXTERNAL_BYTE_ELEMENTS:
573 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
574 case EXTERNAL_SHORT_ELEMENTS:
575 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
576 case EXTERNAL_INT_ELEMENTS:
577 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
578 case EXTERNAL_FLOAT_ELEMENTS:
579 case EXTERNAL_DOUBLE_ELEMENTS:
580 case EXTERNAL_PIXEL_ELEMENTS:
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000581 KeyedStoreStubCompiler::GenerateStoreExternalArray(masm, elements_kind_);
582 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000583 case DICTIONARY_ELEMENTS:
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000584 KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm);
585 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000586 case NON_STRICT_ARGUMENTS_ELEMENTS:
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000587 UNREACHABLE();
588 break;
589 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000590}
591
592
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000593void ArgumentsAccessStub::PrintName(StringStream* stream) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000594 stream->Add("ArgumentsAccessStub_");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000595 switch (type_) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000596 case READ_ELEMENT: stream->Add("ReadElement"); break;
597 case NEW_NON_STRICT_FAST: stream->Add("NewNonStrictFast"); break;
598 case NEW_NON_STRICT_SLOW: stream->Add("NewNonStrictSlow"); break;
599 case NEW_STRICT: stream->Add("NewStrict"); break;
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000600 }
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000601}
602
603
604void CallFunctionStub::PrintName(StringStream* stream) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000605 stream->Add("CallFunctionStub_Args%d", argc_);
606 if (ReceiverMightBeImplicit()) stream->Add("_Implicit");
607 if (RecordCallTarget()) stream->Add("_Recording");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000608}
609
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000610
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000611void CallConstructStub::PrintName(StringStream* stream) {
612 stream->Add("CallConstructStub");
613 if (RecordCallTarget()) stream->Add("_Recording");
614}
615
616
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000617bool ToBooleanStub::Record(Handle<Object> object) {
618 Types old_types(types_);
619 bool to_boolean_value = types_.Record(object);
620 old_types.TraceTransition(types_);
621 return to_boolean_value;
622}
623
624
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000625void ToBooleanStub::PrintName(StringStream* stream) {
626 stream->Add("ToBooleanStub_");
627 types_.Print(stream);
628}
629
630
vegorov@chromium.org7943d462011-08-01 11:41:52 +0000631void ToBooleanStub::Types::Print(StringStream* stream) const {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000632 stream->Add("(");
633 SimpleListPrinter printer(stream);
634 if (IsEmpty()) printer.Add("None");
635 if (Contains(UNDEFINED)) printer.Add("Undefined");
636 if (Contains(BOOLEAN)) printer.Add("Bool");
637 if (Contains(NULL_TYPE)) printer.Add("Null");
638 if (Contains(SMI)) printer.Add("Smi");
639 if (Contains(SPEC_OBJECT)) printer.Add("SpecObject");
640 if (Contains(STRING)) printer.Add("String");
641 if (Contains(SYMBOL)) printer.Add("Symbol");
642 if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
643 stream->Add(")");
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000644}
645
646
vegorov@chromium.org7943d462011-08-01 11:41:52 +0000647void ToBooleanStub::Types::TraceTransition(Types to) const {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000648 #ifdef DEBUG
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000649 if (!FLAG_trace_ic) return;
650 char buffer[100];
651 NoAllocationStringAllocator allocator(buffer,
652 static_cast<unsigned>(sizeof(buffer)));
653 StringStream stream(&allocator);
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000654 stream.Add("[ToBooleanIC : ");
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000655 Print(&stream);
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000656 stream.Add("=>");
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000657 to.Print(&stream);
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000658 stream.Add("]\n");
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000659 stream.OutputToStdOut();
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000660 #endif
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000661}
662
663
664bool ToBooleanStub::Types::Record(Handle<Object> object) {
665 if (object->IsUndefined()) {
666 Add(UNDEFINED);
667 return false;
668 } else if (object->IsBoolean()) {
669 Add(BOOLEAN);
670 return object->IsTrue();
671 } else if (object->IsNull()) {
672 Add(NULL_TYPE);
673 return false;
674 } else if (object->IsSmi()) {
675 Add(SMI);
676 return Smi::cast(*object)->value() != 0;
677 } else if (object->IsSpecObject()) {
678 Add(SPEC_OBJECT);
679 return !object->IsUndetectableObject();
680 } else if (object->IsString()) {
681 Add(STRING);
682 return !object->IsUndetectableObject() &&
683 String::cast(*object)->length() != 0;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000684 } else if (object->IsSymbol()) {
685 Add(SYMBOL);
686 return true;
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000687 } else if (object->IsHeapNumber()) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000688 ASSERT(!object->IsUndetectableObject());
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000689 Add(HEAP_NUMBER);
690 double value = HeapNumber::cast(*object)->value();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000691 return value != 0 && !std::isnan(value);
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000692 } else {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000693 // We should never see an internal object at runtime here!
694 UNREACHABLE();
695 return true;
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000696 }
697}
698
699
vegorov@chromium.org7943d462011-08-01 11:41:52 +0000700bool ToBooleanStub::Types::NeedsMap() const {
701 return Contains(ToBooleanStub::SPEC_OBJECT)
702 || Contains(ToBooleanStub::STRING)
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000703 || Contains(ToBooleanStub::SYMBOL)
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000704 || Contains(ToBooleanStub::HEAP_NUMBER);
705}
706
707
708bool ToBooleanStub::Types::CanBeUndetectable() const {
709 return Contains(ToBooleanStub::SPEC_OBJECT)
710 || Contains(ToBooleanStub::STRING);
vegorov@chromium.org7943d462011-08-01 11:41:52 +0000711}
712
713
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000714void ElementsTransitionAndStoreStub::Generate(MacroAssembler* masm) {
715 Label fail;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000716 AllocationSiteMode mode = AllocationSiteInfo::GetMode(from_, to_);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000717 ASSERT(!IsFastHoleyElementsKind(from_) || IsFastHoleyElementsKind(to_));
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000718 if (!FLAG_trace_elements_transitions) {
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000719 if (IsFastSmiOrObjectElementsKind(to_)) {
720 if (IsFastSmiOrObjectElementsKind(from_)) {
721 ElementsTransitionGenerator::
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000722 GenerateMapChangeElementsTransition(masm, mode, &fail);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000723 } else if (IsFastDoubleElementsKind(from_)) {
724 ASSERT(!IsFastSmiElementsKind(to_));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000725 ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, &fail);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000726 } else {
727 UNREACHABLE();
728 }
729 KeyedStoreStubCompiler::GenerateStoreFastElement(masm,
730 is_jsarray_,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000731 to_,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000732 store_mode_);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000733 } else if (IsFastSmiElementsKind(from_) &&
734 IsFastDoubleElementsKind(to_)) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000735 ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, &fail);
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000736 KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
737 is_jsarray_,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000738 store_mode_);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000739 } else if (IsFastDoubleElementsKind(from_)) {
740 ASSERT(to_ == FAST_HOLEY_DOUBLE_ELEMENTS);
741 ElementsTransitionGenerator::
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000742 GenerateMapChangeElementsTransition(masm, mode, &fail);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000743 } else {
744 UNREACHABLE();
745 }
746 }
747 masm->bind(&fail);
748 KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
749}
750
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000751
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000752void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000753 StubFailureTrampolineStub stub1(NOT_JS_FUNCTION_STUB_MODE);
754 StubFailureTrampolineStub stub2(JS_FUNCTION_STUB_MODE);
755 stub1.GetCode(isolate)->set_is_pregenerated(true);
756 stub2.GetCode(isolate)->set_is_pregenerated(true);
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000757}
758
759
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000760void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
761 intptr_t stack_pointer) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000762 FunctionEntryHook entry_hook = Isolate::Current()->function_entry_hook();
763 ASSERT(entry_hook != NULL);
764 entry_hook(function, stack_pointer);
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000765}
766
767
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000768static void InstallDescriptor(Isolate* isolate, HydrogenCodeStub* stub) {
769 int major_key = stub->MajorKey();
770 CodeStubInterfaceDescriptor* descriptor =
771 isolate->code_stub_interface_descriptor(major_key);
772 if (!descriptor->initialized()) {
773 stub->InitializeInterfaceDescriptor(isolate, descriptor);
774 }
775}
776
777
778void ArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
779 ArrayNoArgumentConstructorStub stub1(GetInitialFastElementsKind());
780 InstallDescriptor(isolate, &stub1);
781 ArraySingleArgumentConstructorStub stub2(GetInitialFastElementsKind());
782 InstallDescriptor(isolate, &stub2);
783 ArrayNArgumentsConstructorStub stub3(GetInitialFastElementsKind());
784 InstallDescriptor(isolate, &stub3);
785}
786
787
788ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
789 : argument_count_(ANY) {
790 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
791}
792
793
794ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
795 int argument_count) {
796 if (argument_count == 0) {
797 argument_count_ = NONE;
798 } else if (argument_count == 1) {
799 argument_count_ = ONE;
800 } else if (argument_count >= 2) {
801 argument_count_ = MORE_THAN_ONE;
802 } else {
803 UNREACHABLE();
804 }
805 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
806}
807
808
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000809void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
810 InternalArrayNoArgumentConstructorStub stub1(FAST_ELEMENTS);
811 InstallDescriptor(isolate, &stub1);
812 InternalArraySingleArgumentConstructorStub stub2(FAST_ELEMENTS);
813 InstallDescriptor(isolate, &stub2);
814 InternalArrayNArgumentsConstructorStub stub3(FAST_ELEMENTS);
815 InstallDescriptor(isolate, &stub3);
816}
817
818InternalArrayConstructorStub::InternalArrayConstructorStub(
819 Isolate* isolate) {
820 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
821}
822
823
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824} } // namespace v8::internal