- add third_party src.
[platform/framework/web/crosswalk.git] / src / v8 / src / code-stubs.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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"
32 #include "cpu-profiler.h"
33 #include "stub-cache.h"
34 #include "factory.h"
35 #include "gdb-jit.h"
36 #include "macro-assembler.h"
37
38 namespace v8 {
39 namespace internal {
40
41
42 CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
43     : register_param_count_(-1),
44       stack_parameter_count_(no_reg),
45       hint_stack_parameter_count_(-1),
46       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
47       register_params_(NULL),
48       deoptimization_handler_(NULL),
49       miss_handler_(),
50       has_miss_handler_(false) { }
51
52
53 bool CodeStub::FindCodeInCache(Code** code_out, Isolate* isolate) {
54   UnseededNumberDictionary* stubs = isolate->heap()->code_stubs();
55   int index = stubs->FindEntry(GetKey());
56   if (index != UnseededNumberDictionary::kNotFound) {
57     *code_out = Code::cast(stubs->ValueAt(index));
58     return true;
59   }
60   return false;
61 }
62
63
64 SmartArrayPointer<const char> CodeStub::GetName() {
65   char buffer[100];
66   NoAllocationStringAllocator allocator(buffer,
67                                         static_cast<unsigned>(sizeof(buffer)));
68   StringStream stream(&allocator);
69   PrintName(&stream);
70   return stream.ToCString();
71 }
72
73
74 void CodeStub::RecordCodeGeneration(Code* code, Isolate* isolate) {
75   SmartArrayPointer<const char> name = GetName();
76   PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, *name));
77   GDBJIT(AddCode(GDBJITInterface::STUB, *name, code));
78   Counters* counters = isolate->counters();
79   counters->total_stubs_code_size()->Increment(code->instruction_size());
80 }
81
82
83 Code::Kind CodeStub::GetCodeKind() const {
84   return Code::STUB;
85 }
86
87
88 Handle<Code> CodeStub::GetCodeCopyFromTemplate(Isolate* isolate) {
89   Handle<Code> ic = GetCode(isolate);
90   ic = isolate->factory()->CopyCode(ic);
91   RecordCodeGeneration(*ic, isolate);
92   return ic;
93 }
94
95
96 Handle<Code> PlatformCodeStub::GenerateCode(Isolate* isolate) {
97   Factory* factory = isolate->factory();
98
99   // Generate the new code.
100   MacroAssembler masm(isolate, NULL, 256);
101
102   {
103     // Update the static counter each time a new code stub is generated.
104     isolate->counters()->code_stubs()->Increment();
105
106     // Nested stubs are not allowed for leaves.
107     AllowStubCallsScope allow_scope(&masm, false);
108
109     // Generate the code for the stub.
110     masm.set_generating_stub(true);
111     NoCurrentFrameScope scope(&masm);
112     Generate(&masm);
113   }
114
115   // Create the code object.
116   CodeDesc desc;
117   masm.GetCode(&desc);
118
119   // Copy the generated code into a heap object.
120   Code::Flags flags = Code::ComputeFlags(
121       GetCodeKind(),
122       GetICState(),
123       GetExtraICState(),
124       GetStubType(),
125       GetStubFlags());
126   Handle<Code> new_object = factory->NewCode(
127       desc, flags, masm.CodeObject(), NeedsImmovableCode());
128   return new_object;
129 }
130
131
132 void CodeStub::VerifyPlatformFeatures(Isolate* isolate) {
133   ASSERT(CpuFeatures::VerifyCrossCompiling());
134 }
135
136
137 Handle<Code> CodeStub::GetCode(Isolate* isolate) {
138   Factory* factory = isolate->factory();
139   Heap* heap = isolate->heap();
140   Code* code;
141   if (UseSpecialCache()
142       ? FindCodeInSpecialCache(&code, isolate)
143       : FindCodeInCache(&code, isolate)) {
144     ASSERT(IsPregenerated(isolate) == code->is_pregenerated());
145     ASSERT(GetCodeKind() == code->kind());
146     return Handle<Code>(code);
147   }
148
149 #ifdef DEBUG
150   VerifyPlatformFeatures(isolate);
151 #endif
152
153   {
154     HandleScope scope(isolate);
155
156     Handle<Code> new_object = GenerateCode(isolate);
157     new_object->set_major_key(MajorKey());
158     FinishCode(new_object);
159     RecordCodeGeneration(*new_object, isolate);
160
161 #ifdef ENABLE_DISASSEMBLER
162     if (FLAG_print_code_stubs) {
163       new_object->Disassemble(*GetName());
164       PrintF("\n");
165     }
166 #endif
167
168     if (UseSpecialCache()) {
169       AddToSpecialCache(new_object);
170     } else {
171       // Update the dictionary and the root in Heap.
172       Handle<UnseededNumberDictionary> dict =
173           factory->DictionaryAtNumberPut(
174               Handle<UnseededNumberDictionary>(heap->code_stubs()),
175               GetKey(),
176               new_object);
177       heap->public_set_code_stubs(*dict);
178     }
179     code = *new_object;
180   }
181
182   Activate(code);
183   ASSERT(!NeedsImmovableCode() ||
184          heap->lo_space()->Contains(code) ||
185          heap->code_space()->FirstPage()->Contains(code->address()));
186   return Handle<Code>(code, isolate);
187 }
188
189
190 const char* CodeStub::MajorName(CodeStub::Major major_key,
191                                 bool allow_unknown_keys) {
192   switch (major_key) {
193 #define DEF_CASE(name) case name: return #name "Stub";
194     CODE_STUB_LIST(DEF_CASE)
195 #undef DEF_CASE
196     default:
197       if (!allow_unknown_keys) {
198         UNREACHABLE();
199       }
200       return NULL;
201   }
202 }
203
204
205 void CodeStub::PrintBaseName(StringStream* stream) {
206   stream->Add("%s", MajorName(MajorKey(), false));
207 }
208
209
210 void CodeStub::PrintName(StringStream* stream) {
211   PrintBaseName(stream);
212   PrintState(stream);
213 }
214
215
216 void BinaryOpStub::PrintBaseName(StringStream* stream) {
217   const char* op_name = Token::Name(op_);
218   const char* ovr = "";
219   if (mode_ == OVERWRITE_LEFT) ovr = "_ReuseLeft";
220   if (mode_ == OVERWRITE_RIGHT) ovr = "_ReuseRight";
221   stream->Add("BinaryOpStub_%s%s", op_name, ovr);
222 }
223
224
225 void BinaryOpStub::PrintState(StringStream* stream) {
226   stream->Add("(");
227   stream->Add(StateToName(left_state_));
228   stream->Add("*");
229   if (fixed_right_arg_.has_value) {
230     stream->Add("%d", fixed_right_arg_.value);
231   } else {
232     stream->Add(StateToName(right_state_));
233   }
234   stream->Add("->");
235   stream->Add(StateToName(result_state_));
236   stream->Add(")");
237 }
238
239
240 Maybe<Handle<Object> > BinaryOpStub::Result(Handle<Object> left,
241                                             Handle<Object> right,
242                                             Isolate* isolate) {
243   Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
244   Builtins::JavaScript func = BinaryOpIC::TokenToJSBuiltin(op_);
245   Object* builtin = builtins->javascript_builtin(func);
246   Handle<JSFunction> builtin_function =
247       Handle<JSFunction>(JSFunction::cast(builtin), isolate);
248   bool caught_exception;
249   Handle<Object> result = Execution::Call(isolate, builtin_function, left,
250       1, &right, &caught_exception);
251   return Maybe<Handle<Object> >(!caught_exception, result);
252 }
253
254
255 void BinaryOpStub::Initialize() {
256   fixed_right_arg_.has_value = false;
257   left_state_ = right_state_ = result_state_ = NONE;
258 }
259
260
261 void BinaryOpStub::Generate(Token::Value op,
262                             State left,
263                             State right,
264                             State result,
265                             OverwriteMode mode,
266                             Isolate* isolate) {
267   BinaryOpStub stub(INITIALIZED);
268   stub.op_ = op;
269   stub.left_state_ = left;
270   stub.right_state_ = right;
271   stub.result_state_ = result;
272   stub.mode_ = mode;
273   stub.GetCode(isolate);
274 }
275
276
277 void BinaryOpStub::Generate(Token::Value op,
278                             State left,
279                             int right,
280                             State result,
281                             OverwriteMode mode,
282                             Isolate* isolate) {
283   BinaryOpStub stub(INITIALIZED);
284   stub.op_ = op;
285   stub.left_state_ = left;
286   stub.fixed_right_arg_.has_value = true;
287   stub.fixed_right_arg_.value = right;
288   stub.right_state_ = SMI;
289   stub.result_state_ = result;
290   stub.mode_ = mode;
291   stub.GetCode(isolate);
292 }
293
294
295 void BinaryOpStub::GenerateAheadOfTime(Isolate* isolate) {
296   Token::Value binop[] = {Token::SUB, Token::MOD, Token::DIV, Token::MUL,
297                           Token::ADD, Token::SAR, Token::BIT_OR, Token::BIT_AND,
298                           Token::BIT_XOR, Token::SHL, Token::SHR};
299   for (unsigned i = 0; i < ARRAY_SIZE(binop); i++) {
300     BinaryOpStub stub(UNINITIALIZED);
301     stub.op_ = binop[i];
302     stub.GetCode(isolate);
303   }
304
305   // TODO(olivf) We should investigate why adding stubs to the snapshot is so
306   // expensive at runtime. When solved we should be able to add most binops to
307   // the snapshot instead of hand-picking them.
308   // Generated list of commonly used stubs
309   Generate(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE, isolate);
310   Generate(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
311   Generate(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
312   Generate(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT, isolate);
313   Generate(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
314   Generate(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
315   Generate(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
316   Generate(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE, isolate);
317   Generate(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
318   Generate(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
319   Generate(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
320   Generate(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
321   Generate(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT, isolate);
322   Generate(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
323   Generate(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
324   Generate(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
325   Generate(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
326   Generate(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
327   Generate(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
328   Generate(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE, isolate);
329   Generate(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
330   Generate(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
331   Generate(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
332   Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
333   Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
334   Generate(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT, isolate);
335   Generate(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
336   Generate(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE, isolate);
337   Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
338   Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
339   Generate(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE, isolate);
340   Generate(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT, isolate);
341   Generate(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE, isolate);
342   Generate(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
343   Generate(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE, isolate);
344   Generate(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT, isolate);
345   Generate(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
346   Generate(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT, isolate);
347   Generate(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
348   Generate(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
349   Generate(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE, isolate);
350   Generate(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT, isolate);
351   Generate(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT, isolate);
352   Generate(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE, isolate);
353   Generate(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
354   Generate(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
355   Generate(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
356   Generate(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
357   Generate(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT, isolate);
358   Generate(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE, isolate);
359   Generate(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
360   Generate(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
361   Generate(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
362   Generate(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
363   Generate(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE, isolate);
364   Generate(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT, isolate);
365   Generate(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT, isolate);
366   Generate(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
367   Generate(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT, isolate);
368   Generate(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
369   Generate(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT, isolate);
370   Generate(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT, isolate);
371   Generate(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
372   Generate(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
373   Generate(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE, isolate);
374   Generate(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
375   Generate(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
376   Generate(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE, isolate);
377   Generate(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT, isolate);
378   Generate(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE, isolate);
379   Generate(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE, isolate);
380   Generate(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
381   Generate(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
382   Generate(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE, isolate);
383   Generate(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE, isolate);
384   Generate(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
385   Generate(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE, isolate);
386   Generate(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
387   Generate(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT, isolate);
388   Generate(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE, isolate);
389   Generate(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
390   Generate(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
391   Generate(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE, isolate);
392   Generate(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
393   Generate(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
394   Generate(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
395   Generate(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE, isolate);
396   Generate(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE, isolate);
397   Generate(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
398   Generate(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
399   Generate(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
400   Generate(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
401   Generate(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
402   Generate(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
403   Generate(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
404   Generate(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE, isolate);
405   Generate(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
406   Generate(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT, isolate);
407   Generate(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
408   Generate(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
409   Generate(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
410   Generate(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE, isolate);
411   Generate(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT, isolate);
412   Generate(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
413   Generate(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE, isolate);
414   Generate(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
415   Generate(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
416   Generate(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
417   Generate(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT, isolate);
418   Generate(Token::MOD, SMI, 2, SMI, NO_OVERWRITE, isolate);
419   Generate(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE, isolate);
420   Generate(Token::MOD, SMI, 32, SMI, NO_OVERWRITE, isolate);
421   Generate(Token::MOD, SMI, 4, SMI, NO_OVERWRITE, isolate);
422   Generate(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT, isolate);
423   Generate(Token::MOD, SMI, 8, SMI, NO_OVERWRITE, isolate);
424   Generate(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE, isolate);
425   Generate(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
426   Generate(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE, isolate);
427   Generate(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
428   Generate(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
429   Generate(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
430   Generate(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE, isolate);
431   Generate(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
432   Generate(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE, isolate);
433   Generate(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
434   Generate(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
435   Generate(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT, isolate);
436   Generate(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
437   Generate(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
438   Generate(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
439   Generate(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
440   Generate(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
441   Generate(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE, isolate);
442   Generate(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
443   Generate(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
444   Generate(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
445   Generate(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
446   Generate(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
447   Generate(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE, isolate);
448   Generate(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE, isolate);
449   Generate(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT, isolate);
450   Generate(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE, isolate);
451   Generate(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
452   Generate(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
453   Generate(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
454   Generate(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
455   Generate(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
456   Generate(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
457   Generate(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
458   Generate(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
459   Generate(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
460   Generate(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE, isolate);
461   Generate(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
462   Generate(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE, isolate);
463   Generate(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
464   Generate(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
465   Generate(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE, isolate);
466   Generate(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT, isolate);
467   Generate(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT, isolate);
468   Generate(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE, isolate);
469   Generate(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
470   Generate(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
471   Generate(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
472   Generate(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT, isolate);
473   Generate(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
474   Generate(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
475   Generate(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT, isolate);
476   Generate(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT, isolate);
477   Generate(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE, isolate);
478   Generate(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
479   Generate(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
480   Generate(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE, isolate);
481   Generate(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
482   Generate(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
483   Generate(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
484   Generate(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
485   Generate(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
486   Generate(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
487   Generate(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
488   Generate(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
489   Generate(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
490   Generate(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
491   Generate(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
492   Generate(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
493   Generate(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
494   Generate(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE, isolate);
495   Generate(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
496   Generate(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
497   Generate(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
498   Generate(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE, isolate);
499   Generate(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
500   Generate(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
501 }
502
503
504 bool BinaryOpStub::can_encode_arg_value(int32_t value) const {
505   return op_ == Token::MOD && value > 0 && IsPowerOf2(value) &&
506          FixedRightArgValueBits::is_valid(WhichPowerOf2(value));
507 }
508
509
510 int BinaryOpStub::encode_arg_value(int32_t value) const {
511   ASSERT(can_encode_arg_value(value));
512   return WhichPowerOf2(value);
513 }
514
515
516 int32_t BinaryOpStub::decode_arg_value(int value)  const {
517   return 1 << value;
518 }
519
520
521 int BinaryOpStub::encode_token(Token::Value op) const {
522   ASSERT(op >= FIRST_TOKEN && op <= LAST_TOKEN);
523   return op - FIRST_TOKEN;
524 }
525
526
527 Token::Value BinaryOpStub::decode_token(int op) const {
528   int res = op + FIRST_TOKEN;
529   ASSERT(res >= FIRST_TOKEN && res <= LAST_TOKEN);
530   return static_cast<Token::Value>(res);
531 }
532
533
534 const char* BinaryOpStub::StateToName(State state) {
535   switch (state) {
536     case NONE:
537       return "None";
538     case SMI:
539       return "Smi";
540     case INT32:
541       return "Int32";
542     case NUMBER:
543       return "Number";
544     case STRING:
545       return "String";
546     case GENERIC:
547       return "Generic";
548   }
549   return "";
550 }
551
552
553 void BinaryOpStub::UpdateStatus(Handle<Object> left,
554                                 Handle<Object> right,
555                                 Maybe<Handle<Object> > result) {
556   int old_state = GetExtraICState();
557
558   UpdateStatus(left, &left_state_);
559   UpdateStatus(right, &right_state_);
560
561   int32_t value;
562   bool new_has_fixed_right_arg =
563       right->ToInt32(&value) && can_encode_arg_value(value) &&
564       (left_state_ == SMI || left_state_ == INT32) &&
565       (result_state_ == NONE || !fixed_right_arg_.has_value);
566
567   fixed_right_arg_ = Maybe<int32_t>(new_has_fixed_right_arg, value);
568
569   if (result.has_value) UpdateStatus(result.value, &result_state_);
570
571   State max_input = Max(left_state_, right_state_);
572
573   if (!has_int_result() && op_ != Token::SHR &&
574       max_input <= NUMBER && max_input > result_state_) {
575     result_state_ = max_input;
576   }
577
578   ASSERT(result_state_ <= (has_int_result() ? INT32 : NUMBER) ||
579          op_ == Token::ADD);
580
581   if (old_state == GetExtraICState()) {
582     // Tagged operations can lead to non-truncating HChanges
583     if (left->IsUndefined() || left->IsBoolean()) {
584       left_state_ = GENERIC;
585     } else if (right->IsUndefined() || right->IsBoolean()) {
586       right_state_ = GENERIC;
587     } else {
588       // Since the fpu is to precise, we might bail out on numbers which
589       // actually would truncate with 64 bit precision.
590       ASSERT(!CpuFeatures::IsSupported(SSE2) &&
591              result_state_ <= INT32);
592       result_state_ = NUMBER;
593     }
594   }
595 }
596
597
598 void BinaryOpStub::UpdateStatus(Handle<Object> object,
599                                 State* state) {
600   bool is_truncating = (op_ == Token::BIT_AND || op_ == Token::BIT_OR ||
601                         op_ == Token::BIT_XOR || op_ == Token::SAR ||
602                         op_ == Token::SHL || op_ == Token::SHR);
603   v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(object);
604   if (object->IsBoolean() && is_truncating) {
605     // Booleans are converted by truncating by HChange.
606     type = TypeInfo::Integer32();
607   }
608   if (object->IsUndefined()) {
609     // Undefined will be automatically truncated for us by HChange.
610     type = is_truncating ? TypeInfo::Integer32() : TypeInfo::Double();
611   }
612   State int_state = SmiValuesAre32Bits() ? NUMBER : INT32;
613   State new_state = NONE;
614   if (type.IsSmi()) {
615     new_state = SMI;
616   } else if (type.IsInteger32()) {
617     new_state = int_state;
618   } else if (type.IsNumber()) {
619     new_state = NUMBER;
620   } else if (object->IsString() && operation() == Token::ADD) {
621     new_state = STRING;
622   } else {
623     new_state = GENERIC;
624   }
625   if ((new_state <= NUMBER && *state >  NUMBER) ||
626       (new_state >  NUMBER && *state <= NUMBER && *state != NONE)) {
627     new_state = GENERIC;
628   }
629   *state = Max(*state, new_state);
630 }
631
632
633 Handle<Type> BinaryOpStub::StateToType(State state,
634                                        Isolate* isolate) {
635   Handle<Type> t = handle(Type::None(), isolate);
636   switch (state) {
637     case NUMBER:
638       t = handle(Type::Union(t, handle(Type::Double(), isolate)), isolate);
639       // Fall through.
640     case INT32:
641       t = handle(Type::Union(t, handle(Type::Signed32(), isolate)), isolate);
642       // Fall through.
643     case SMI:
644       t = handle(Type::Union(t, handle(Type::Smi(), isolate)), isolate);
645       break;
646
647     case STRING:
648       t = handle(Type::Union(t, handle(Type::String(), isolate)), isolate);
649       break;
650     case GENERIC:
651       return handle(Type::Any(), isolate);
652       break;
653     case NONE:
654       break;
655   }
656   return t;
657 }
658
659
660 Handle<Type> BinaryOpStub::GetLeftType(Isolate* isolate) const {
661   return StateToType(left_state_, isolate);
662 }
663
664
665 Handle<Type> BinaryOpStub::GetRightType(Isolate* isolate) const {
666   return StateToType(right_state_, isolate);
667 }
668
669
670 Handle<Type> BinaryOpStub::GetResultType(Isolate* isolate) const {
671   if (HasSideEffects(isolate)) return StateToType(NONE, isolate);
672   if (result_state_ == GENERIC && op_ == Token::ADD) {
673     return handle(Type::Union(handle(Type::Number(), isolate),
674                               handle(Type::String(), isolate)), isolate);
675   }
676   ASSERT(result_state_ != GENERIC);
677   if (result_state_ == NUMBER && op_ == Token::SHR) {
678     return handle(Type::Unsigned32(), isolate);
679   }
680   return StateToType(result_state_, isolate);
681 }
682
683
684 InlineCacheState ICCompareStub::GetICState() {
685   CompareIC::State state = Max(left_, right_);
686   switch (state) {
687     case CompareIC::UNINITIALIZED:
688       return ::v8::internal::UNINITIALIZED;
689     case CompareIC::SMI:
690     case CompareIC::NUMBER:
691     case CompareIC::INTERNALIZED_STRING:
692     case CompareIC::STRING:
693     case CompareIC::UNIQUE_NAME:
694     case CompareIC::OBJECT:
695     case CompareIC::KNOWN_OBJECT:
696       return MONOMORPHIC;
697     case CompareIC::GENERIC:
698       return ::v8::internal::GENERIC;
699   }
700   UNREACHABLE();
701   return ::v8::internal::UNINITIALIZED;
702 }
703
704
705 void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
706   ASSERT(*known_map_ != NULL);
707   Isolate* isolate = new_object->GetIsolate();
708   Factory* factory = isolate->factory();
709   return Map::UpdateCodeCache(known_map_,
710                               strict() ?
711                                   factory->strict_compare_ic_string() :
712                                   factory->compare_ic_string(),
713                               new_object);
714 }
715
716
717 bool ICCompareStub::FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
718   Factory* factory = isolate->factory();
719   Code::Flags flags = Code::ComputeFlags(
720       GetCodeKind(),
721       UNINITIALIZED);
722   ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
723   Handle<Object> probe(
724       known_map_->FindInCodeCache(
725         strict() ?
726             *factory->strict_compare_ic_string() :
727             *factory->compare_ic_string(),
728         flags),
729       isolate);
730   if (probe->IsCode()) {
731     *code_out = Code::cast(*probe);
732 #ifdef DEBUG
733     Token::Value cached_op;
734     ICCompareStub::DecodeMinorKey((*code_out)->stub_info(), NULL, NULL, NULL,
735                                   &cached_op);
736     ASSERT(op_ == cached_op);
737 #endif
738     return true;
739   }
740   return false;
741 }
742
743
744 int ICCompareStub::MinorKey() {
745   return OpField::encode(op_ - Token::EQ) |
746          LeftStateField::encode(left_) |
747          RightStateField::encode(right_) |
748          HandlerStateField::encode(state_);
749 }
750
751
752 void ICCompareStub::DecodeMinorKey(int minor_key,
753                                    CompareIC::State* left_state,
754                                    CompareIC::State* right_state,
755                                    CompareIC::State* handler_state,
756                                    Token::Value* op) {
757   if (left_state) {
758     *left_state =
759         static_cast<CompareIC::State>(LeftStateField::decode(minor_key));
760   }
761   if (right_state) {
762     *right_state =
763         static_cast<CompareIC::State>(RightStateField::decode(minor_key));
764   }
765   if (handler_state) {
766     *handler_state =
767         static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
768   }
769   if (op) {
770     *op = static_cast<Token::Value>(OpField::decode(minor_key) + Token::EQ);
771   }
772 }
773
774
775 void ICCompareStub::Generate(MacroAssembler* masm) {
776   switch (state_) {
777     case CompareIC::UNINITIALIZED:
778       GenerateMiss(masm);
779       break;
780     case CompareIC::SMI:
781       GenerateSmis(masm);
782       break;
783     case CompareIC::NUMBER:
784       GenerateNumbers(masm);
785       break;
786     case CompareIC::STRING:
787       GenerateStrings(masm);
788       break;
789     case CompareIC::INTERNALIZED_STRING:
790       GenerateInternalizedStrings(masm);
791       break;
792     case CompareIC::UNIQUE_NAME:
793       GenerateUniqueNames(masm);
794       break;
795     case CompareIC::OBJECT:
796       GenerateObjects(masm);
797       break;
798     case CompareIC::KNOWN_OBJECT:
799       ASSERT(*known_map_ != NULL);
800       GenerateKnownObjects(masm);
801       break;
802     case CompareIC::GENERIC:
803       GenerateGeneric(masm);
804       break;
805   }
806 }
807
808
809 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
810   ASSERT(!state_.Contains(GENERIC));
811   State old_state(state_);
812   if (object->IsNull()) {
813     state_.Add(NULL_TYPE);
814   } else if (object->IsUndefined()) {
815     state_.Add(UNDEFINED);
816   } else if (object->IsUndetectableObject() ||
817              object->IsOddball() ||
818              !object->IsHeapObject()) {
819     state_.RemoveAll();
820     state_.Add(GENERIC);
821   } else if (IsMonomorphic()) {
822     state_.RemoveAll();
823     state_.Add(GENERIC);
824   } else {
825     state_.Add(MONOMORPHIC_MAP);
826   }
827   TraceTransition(old_state, state_);
828 }
829
830
831 template<class StateType>
832 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
833   // Note: Although a no-op transition is semantically OK, it is hinting at a
834   // bug somewhere in our state transition machinery.
835   ASSERT(from != to);
836   #ifdef DEBUG
837   if (!FLAG_trace_ic) return;
838   char buffer[100];
839   NoAllocationStringAllocator allocator(buffer,
840                                         static_cast<unsigned>(sizeof(buffer)));
841   StringStream stream(&allocator);
842   stream.Add("[");
843   PrintBaseName(&stream);
844   stream.Add(": ");
845   from.Print(&stream);
846   stream.Add("=>");
847   to.Print(&stream);
848   stream.Add("]\n");
849   stream.OutputToStdOut();
850   #endif
851 }
852
853
854 void CompareNilICStub::PrintBaseName(StringStream* stream) {
855   CodeStub::PrintBaseName(stream);
856   stream->Add((nil_value_ == kNullValue) ? "(NullValue)":
857                                            "(UndefinedValue)");
858 }
859
860
861 void CompareNilICStub::PrintState(StringStream* stream) {
862   state_.Print(stream);
863 }
864
865
866 void CompareNilICStub::State::Print(StringStream* stream) const {
867   stream->Add("(");
868   SimpleListPrinter printer(stream);
869   if (IsEmpty()) printer.Add("None");
870   if (Contains(UNDEFINED)) printer.Add("Undefined");
871   if (Contains(NULL_TYPE)) printer.Add("Null");
872   if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
873   if (Contains(GENERIC)) printer.Add("Generic");
874   stream->Add(")");
875 }
876
877
878 Handle<Type> CompareNilICStub::GetType(
879     Isolate* isolate,
880     Handle<Map> map) {
881   if (state_.Contains(CompareNilICStub::GENERIC)) {
882     return handle(Type::Any(), isolate);
883   }
884
885   Handle<Type> result(Type::None(), isolate);
886   if (state_.Contains(CompareNilICStub::UNDEFINED)) {
887     result = handle(Type::Union(result, handle(Type::Undefined(), isolate)),
888                     isolate);
889   }
890   if (state_.Contains(CompareNilICStub::NULL_TYPE)) {
891     result = handle(Type::Union(result, handle(Type::Null(), isolate)),
892                     isolate);
893   }
894   if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
895     Type* type = map.is_null() ? Type::Detectable() : Type::Class(map);
896     result = handle(Type::Union(result, handle(type, isolate)), isolate);
897   }
898
899   return result;
900 }
901
902
903 Handle<Type> CompareNilICStub::GetInputType(
904     Isolate* isolate,
905     Handle<Map> map) {
906   Handle<Type> output_type = GetType(isolate, map);
907   Handle<Type> nil_type = handle(nil_value_ == kNullValue
908       ? Type::Null() : Type::Undefined(), isolate);
909   return handle(Type::Union(output_type, nil_type), isolate);
910 }
911
912
913 void InstanceofStub::PrintName(StringStream* stream) {
914   const char* args = "";
915   if (HasArgsInRegisters()) {
916     args = "_REGS";
917   }
918
919   const char* inline_check = "";
920   if (HasCallSiteInlineCheck()) {
921     inline_check = "_INLINE";
922   }
923
924   const char* return_true_false_object = "";
925   if (ReturnTrueFalseObject()) {
926     return_true_false_object = "_TRUEFALSE";
927   }
928
929   stream->Add("InstanceofStub%s%s%s",
930               args,
931               inline_check,
932               return_true_false_object);
933 }
934
935
936 void JSEntryStub::FinishCode(Handle<Code> code) {
937   Handle<FixedArray> handler_table =
938       code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
939   handler_table->set(0, Smi::FromInt(handler_offset_));
940   code->set_handler_table(*handler_table);
941 }
942
943
944 void KeyedLoadDictionaryElementStub::Generate(MacroAssembler* masm) {
945   KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
946 }
947
948
949 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
950   CreateAllocationSiteStub stub;
951   stub.GetCode(isolate)->set_is_pregenerated(true);
952 }
953
954
955 void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
956   switch (elements_kind_) {
957     case FAST_ELEMENTS:
958     case FAST_HOLEY_ELEMENTS:
959     case FAST_SMI_ELEMENTS:
960     case FAST_HOLEY_SMI_ELEMENTS:
961     case FAST_DOUBLE_ELEMENTS:
962     case FAST_HOLEY_DOUBLE_ELEMENTS:
963     case EXTERNAL_BYTE_ELEMENTS:
964     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
965     case EXTERNAL_SHORT_ELEMENTS:
966     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
967     case EXTERNAL_INT_ELEMENTS:
968     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
969     case EXTERNAL_FLOAT_ELEMENTS:
970     case EXTERNAL_DOUBLE_ELEMENTS:
971     case EXTERNAL_PIXEL_ELEMENTS:
972       UNREACHABLE();
973       break;
974     case DICTIONARY_ELEMENTS:
975       KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm);
976       break;
977     case NON_STRICT_ARGUMENTS_ELEMENTS:
978       UNREACHABLE();
979       break;
980   }
981 }
982
983
984 void ArgumentsAccessStub::PrintName(StringStream* stream) {
985   stream->Add("ArgumentsAccessStub_");
986   switch (type_) {
987     case READ_ELEMENT: stream->Add("ReadElement"); break;
988     case NEW_NON_STRICT_FAST: stream->Add("NewNonStrictFast"); break;
989     case NEW_NON_STRICT_SLOW: stream->Add("NewNonStrictSlow"); break;
990     case NEW_STRICT: stream->Add("NewStrict"); break;
991   }
992 }
993
994
995 void CallFunctionStub::PrintName(StringStream* stream) {
996   stream->Add("CallFunctionStub_Args%d", argc_);
997   if (ReceiverMightBeImplicit()) stream->Add("_Implicit");
998   if (RecordCallTarget()) stream->Add("_Recording");
999 }
1000
1001
1002 void CallConstructStub::PrintName(StringStream* stream) {
1003   stream->Add("CallConstructStub");
1004   if (RecordCallTarget()) stream->Add("_Recording");
1005 }
1006
1007
1008 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
1009   Types old_types(types_);
1010   bool to_boolean_value = types_.UpdateStatus(object);
1011   TraceTransition(old_types, types_);
1012   return to_boolean_value;
1013 }
1014
1015
1016 void ToBooleanStub::PrintState(StringStream* stream) {
1017   types_.Print(stream);
1018 }
1019
1020
1021 void ToBooleanStub::Types::Print(StringStream* stream) const {
1022   stream->Add("(");
1023   SimpleListPrinter printer(stream);
1024   if (IsEmpty()) printer.Add("None");
1025   if (Contains(UNDEFINED)) printer.Add("Undefined");
1026   if (Contains(BOOLEAN)) printer.Add("Bool");
1027   if (Contains(NULL_TYPE)) printer.Add("Null");
1028   if (Contains(SMI)) printer.Add("Smi");
1029   if (Contains(SPEC_OBJECT)) printer.Add("SpecObject");
1030   if (Contains(STRING)) printer.Add("String");
1031   if (Contains(SYMBOL)) printer.Add("Symbol");
1032   if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
1033   stream->Add(")");
1034 }
1035
1036
1037 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
1038   if (object->IsUndefined()) {
1039     Add(UNDEFINED);
1040     return false;
1041   } else if (object->IsBoolean()) {
1042     Add(BOOLEAN);
1043     return object->IsTrue();
1044   } else if (object->IsNull()) {
1045     Add(NULL_TYPE);
1046     return false;
1047   } else if (object->IsSmi()) {
1048     Add(SMI);
1049     return Smi::cast(*object)->value() != 0;
1050   } else if (object->IsSpecObject()) {
1051     Add(SPEC_OBJECT);
1052     return !object->IsUndetectableObject();
1053   } else if (object->IsString()) {
1054     Add(STRING);
1055     return !object->IsUndetectableObject() &&
1056         String::cast(*object)->length() != 0;
1057   } else if (object->IsSymbol()) {
1058     Add(SYMBOL);
1059     return true;
1060   } else if (object->IsHeapNumber()) {
1061     ASSERT(!object->IsUndetectableObject());
1062     Add(HEAP_NUMBER);
1063     double value = HeapNumber::cast(*object)->value();
1064     return value != 0 && !std::isnan(value);
1065   } else {
1066     // We should never see an internal object at runtime here!
1067     UNREACHABLE();
1068     return true;
1069   }
1070 }
1071
1072
1073 bool ToBooleanStub::Types::NeedsMap() const {
1074   return Contains(ToBooleanStub::SPEC_OBJECT)
1075       || Contains(ToBooleanStub::STRING)
1076       || Contains(ToBooleanStub::SYMBOL)
1077       || Contains(ToBooleanStub::HEAP_NUMBER);
1078 }
1079
1080
1081 bool ToBooleanStub::Types::CanBeUndetectable() const {
1082   return Contains(ToBooleanStub::SPEC_OBJECT)
1083       || Contains(ToBooleanStub::STRING);
1084 }
1085
1086
1087 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
1088   StubFailureTrampolineStub stub1(NOT_JS_FUNCTION_STUB_MODE);
1089   StubFailureTrampolineStub stub2(JS_FUNCTION_STUB_MODE);
1090   stub1.GetCode(isolate)->set_is_pregenerated(true);
1091   stub2.GetCode(isolate)->set_is_pregenerated(true);
1092 }
1093
1094
1095 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
1096                                                intptr_t stack_pointer,
1097                                                Isolate* isolate) {
1098   FunctionEntryHook entry_hook = isolate->function_entry_hook();
1099   ASSERT(entry_hook != NULL);
1100   entry_hook(function, stack_pointer);
1101 }
1102
1103
1104 static void InstallDescriptor(Isolate* isolate, HydrogenCodeStub* stub) {
1105   int major_key = stub->MajorKey();
1106   CodeStubInterfaceDescriptor* descriptor =
1107       isolate->code_stub_interface_descriptor(major_key);
1108   if (!descriptor->initialized()) {
1109     stub->InitializeInterfaceDescriptor(isolate, descriptor);
1110   }
1111 }
1112
1113
1114 void ArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
1115   ArrayNoArgumentConstructorStub stub1(GetInitialFastElementsKind());
1116   InstallDescriptor(isolate, &stub1);
1117   ArraySingleArgumentConstructorStub stub2(GetInitialFastElementsKind());
1118   InstallDescriptor(isolate, &stub2);
1119   ArrayNArgumentsConstructorStub stub3(GetInitialFastElementsKind());
1120   InstallDescriptor(isolate, &stub3);
1121 }
1122
1123
1124 void NumberToStringStub::InstallDescriptors(Isolate* isolate) {
1125   NumberToStringStub stub;
1126   InstallDescriptor(isolate, &stub);
1127 }
1128
1129
1130 void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
1131   FastNewClosureStub stub(STRICT_MODE, false);
1132   InstallDescriptor(isolate, &stub);
1133 }
1134
1135
1136 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
1137     : argument_count_(ANY) {
1138   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1139 }
1140
1141
1142 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
1143                                            int argument_count) {
1144   if (argument_count == 0) {
1145     argument_count_ = NONE;
1146   } else if (argument_count == 1) {
1147     argument_count_ = ONE;
1148   } else if (argument_count >= 2) {
1149     argument_count_ = MORE_THAN_ONE;
1150   } else {
1151     UNREACHABLE();
1152   }
1153   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1154 }
1155
1156
1157 void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
1158   InternalArrayNoArgumentConstructorStub stub1(FAST_ELEMENTS);
1159   InstallDescriptor(isolate, &stub1);
1160   InternalArraySingleArgumentConstructorStub stub2(FAST_ELEMENTS);
1161   InstallDescriptor(isolate, &stub2);
1162   InternalArrayNArgumentsConstructorStub stub3(FAST_ELEMENTS);
1163   InstallDescriptor(isolate, &stub3);
1164 }
1165
1166 InternalArrayConstructorStub::InternalArrayConstructorStub(
1167     Isolate* isolate) {
1168   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1169 }
1170
1171
1172 } }  // namespace v8::internal