blob: bc722bbeb88bb475593a82bf109fac0d4f6dc934 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 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 "codegen-inl.h"
Steve Blockd0582a62009-12-15 09:54:21 +000032#include "compiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033#include "debug.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000034#include "liveedit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "oprofile-agent.h"
36#include "prettyprinter.h"
37#include "register-allocator-inl.h"
38#include "rewriter.h"
39#include "runtime.h"
40#include "scopeinfo.h"
41#include "stub-cache.h"
42
43namespace v8 {
44namespace internal {
45
Andrei Popescu31002712010-02-23 13:46:05 +000046#define __ ACCESS_MASM(masm_)
47
48#ifdef DEBUG
49
50Comment::Comment(MacroAssembler* masm, const char* msg)
51 : masm_(masm), msg_(msg) {
52 __ RecordComment(msg);
53}
54
55
56Comment::~Comment() {
57 if (msg_[0] == '[') __ RecordComment("]");
58}
59
60#endif // DEBUG
61
62#undef __
63
Steve Blocka7e24c12009-10-30 11:49:00 +000064
65CodeGenerator* CodeGeneratorScope::top_ = NULL;
66
67
68DeferredCode::DeferredCode()
69 : masm_(CodeGeneratorScope::Current()->masm()),
70 statement_position_(masm_->current_statement_position()),
71 position_(masm_->current_position()) {
72 ASSERT(statement_position_ != RelocInfo::kNoPosition);
73 ASSERT(position_ != RelocInfo::kNoPosition);
74
75 CodeGeneratorScope::Current()->AddDeferred(this);
76#ifdef DEBUG
77 comment_ = "";
78#endif
79
80 // Copy the register locations from the code generator's frame.
81 // These are the registers that will be spilled on entry to the
82 // deferred code and restored on exit.
83 VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
84 int sp_offset = frame->fp_relative(frame->stack_pointer_);
85 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
86 int loc = frame->register_location(i);
87 if (loc == VirtualFrame::kIllegalIndex) {
88 registers_[i] = kIgnore;
89 } else if (frame->elements_[loc].is_synced()) {
90 // Needs to be restored on exit but not saved on entry.
91 registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
92 } else {
93 int offset = frame->fp_relative(loc);
94 registers_[i] = (offset < sp_offset) ? kPush : offset;
95 }
96 }
97}
98
99
100void CodeGenerator::ProcessDeferred() {
101 while (!deferred_.is_empty()) {
102 DeferredCode* code = deferred_.RemoveLast();
103 ASSERT(masm_ == code->masm());
104 // Record position of deferred code stub.
105 masm_->RecordStatementPosition(code->statement_position());
106 if (code->position() != RelocInfo::kNoPosition) {
107 masm_->RecordPosition(code->position());
108 }
109 // Generate the code.
110 Comment cmnt(masm_, code->comment());
111 masm_->bind(code->entry_label());
112 code->SaveRegisters();
113 code->Generate();
114 code->RestoreRegisters();
115 masm_->jmp(code->exit_label());
116 }
117}
118
119
120void CodeGenerator::SetFrame(VirtualFrame* new_frame,
121 RegisterFile* non_frame_registers) {
122 RegisterFile saved_counts;
123 if (has_valid_frame()) {
124 frame_->DetachFromCodeGenerator();
125 // The remaining register reference counts are the non-frame ones.
126 allocator_->SaveTo(&saved_counts);
127 }
128
129 if (new_frame != NULL) {
130 // Restore the non-frame register references that go with the new frame.
131 allocator_->RestoreFrom(non_frame_registers);
132 new_frame->AttachToCodeGenerator();
133 }
134
135 frame_ = new_frame;
136 saved_counts.CopyTo(non_frame_registers);
137}
138
139
140void CodeGenerator::DeleteFrame() {
141 if (has_valid_frame()) {
142 frame_->DetachFromCodeGenerator();
143 frame_ = NULL;
144 }
145}
146
147
Andrei Popescu31002712010-02-23 13:46:05 +0000148void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000149#ifdef DEBUG
150 bool print_source = false;
151 bool print_ast = false;
Steve Block3ce2e202009-11-05 08:53:23 +0000152 bool print_json_ast = false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 const char* ftype;
154
155 if (Bootstrapper::IsActive()) {
156 print_source = FLAG_print_builtin_source;
157 print_ast = FLAG_print_builtin_ast;
Steve Block3ce2e202009-11-05 08:53:23 +0000158 print_json_ast = FLAG_print_builtin_json_ast;
Steve Blocka7e24c12009-10-30 11:49:00 +0000159 ftype = "builtin";
160 } else {
161 print_source = FLAG_print_source;
162 print_ast = FLAG_print_ast;
Steve Block3ce2e202009-11-05 08:53:23 +0000163 print_json_ast = FLAG_print_json_ast;
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 ftype = "user-defined";
165 }
166
167 if (FLAG_trace_codegen || print_source || print_ast) {
168 PrintF("*** Generate code for %s function: ", ftype);
Andrei Popescu31002712010-02-23 13:46:05 +0000169 info->function()->name()->ShortPrint();
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 PrintF(" ***\n");
171 }
172
173 if (print_source) {
Andrei Popescu31002712010-02-23 13:46:05 +0000174 PrintF("--- Source from AST ---\n%s\n",
175 PrettyPrinter().PrintProgram(info->function()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 }
177
178 if (print_ast) {
Andrei Popescu31002712010-02-23 13:46:05 +0000179 PrintF("--- AST ---\n%s\n",
180 AstPrinter().PrintProgram(info->function()));
Steve Block3ce2e202009-11-05 08:53:23 +0000181 }
182
183 if (print_json_ast) {
184 JsonAstBuilder builder;
Andrei Popescu31002712010-02-23 13:46:05 +0000185 PrintF("%s", builder.BuildProgram(info->function()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000186 }
187#endif // DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +0000188}
Steve Blocka7e24c12009-10-30 11:49:00 +0000189
Steve Blocka7e24c12009-10-30 11:49:00 +0000190
Andrei Popescu31002712010-02-23 13:46:05 +0000191Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
Steve Block3ce2e202009-11-05 08:53:23 +0000192 Code::Flags flags,
Andrei Popescu31002712010-02-23 13:46:05 +0000193 CompilationInfo* info) {
Steve Block3ce2e202009-11-05 08:53:23 +0000194 // Allocate and install the code.
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 CodeDesc desc;
Steve Block3ce2e202009-11-05 08:53:23 +0000196 masm->GetCode(&desc);
Andrei Popescu31002712010-02-23 13:46:05 +0000197 ZoneScopeInfo sinfo(info->scope());
Steve Block3ce2e202009-11-05 08:53:23 +0000198 Handle<Code> code =
199 Factory::NewCode(desc, &sinfo, flags, masm->CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +0000200
Steve Blocka7e24c12009-10-30 11:49:00 +0000201#ifdef ENABLE_DISASSEMBLER
Steve Block3ce2e202009-11-05 08:53:23 +0000202 bool print_code = Bootstrapper::IsActive()
203 ? FLAG_print_builtin_code
204 : FLAG_print_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (print_code) {
206 // Print the source code if available.
Andrei Popescu31002712010-02-23 13:46:05 +0000207 Handle<Script> script = info->script();
208 FunctionLiteral* function = info->function();
Steve Blocka7e24c12009-10-30 11:49:00 +0000209 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
210 PrintF("--- Raw source ---\n");
211 StringInputBuffer stream(String::cast(script->source()));
Andrei Popescu31002712010-02-23 13:46:05 +0000212 stream.Seek(function->start_position());
Steve Block3ce2e202009-11-05 08:53:23 +0000213 // fun->end_position() points to the last character in the stream. We
Steve Blocka7e24c12009-10-30 11:49:00 +0000214 // need to compensate by adding one to calculate the length.
Andrei Popescu31002712010-02-23 13:46:05 +0000215 int source_len =
216 function->end_position() - function->start_position() + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000217 for (int i = 0; i < source_len; i++) {
218 if (stream.has_more()) PrintF("%c", stream.GetNext());
219 }
220 PrintF("\n\n");
221 }
222 PrintF("--- Code ---\n");
Andrei Popescu31002712010-02-23 13:46:05 +0000223 code->Disassemble(*function->name()->ToCString());
Steve Blocka7e24c12009-10-30 11:49:00 +0000224 }
225#endif // ENABLE_DISASSEMBLER
226
227 if (!code.is_null()) {
228 Counters::total_compiled_code_size.Increment(code->instruction_size());
229 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000230 return code;
231}
232
233
Steve Block3ce2e202009-11-05 08:53:23 +0000234// Generate the code. Takes a function literal, generates code for it, assemble
235// all the pieces into a Code object. This function is only to be called by
236// the compiler.cc code.
Andrei Popescu31002712010-02-23 13:46:05 +0000237Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000238 LiveEditFunctionTracker live_edit_tracker(info->function());
Andrei Popescu31002712010-02-23 13:46:05 +0000239 Handle<Script> script = info->script();
Leon Clarked91b9f72010-01-27 17:25:45 +0000240 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
241 int len = String::cast(script->source())->length();
242 Counters::total_old_codegen_source_size.Increment(len);
243 }
Andrei Popescu31002712010-02-23 13:46:05 +0000244 MakeCodePrologue(info);
Steve Block3ce2e202009-11-05 08:53:23 +0000245 // Generate code.
246 const int kInitialBufferSize = 4 * KB;
Leon Clarke4515c472010-02-03 11:58:03 +0000247 MacroAssembler masm(NULL, kInitialBufferSize);
Andrei Popescu31002712010-02-23 13:46:05 +0000248 CodeGenerator cgen(&masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000249 CodeGeneratorScope scope(&cgen);
Andrei Popescu402d9372010-02-26 13:31:12 +0000250 live_edit_tracker.RecordFunctionScope(info->function()->scope());
251 cgen.Generate(info);
Steve Block3ce2e202009-11-05 08:53:23 +0000252 if (cgen.HasStackOverflow()) {
253 ASSERT(!Top::has_pending_exception());
254 return Handle<Code>::null();
255 }
256
257 InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
258 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
Andrei Popescu402d9372010-02-26 13:31:12 +0000259 Handle<Code> result = MakeCodeEpilogue(cgen.masm(), flags, info);
260 live_edit_tracker.RecordFunctionCode(result);
261 return result;
Steve Block3ce2e202009-11-05 08:53:23 +0000262}
263
264
Steve Blocka7e24c12009-10-30 11:49:00 +0000265#ifdef ENABLE_LOGGING_AND_PROFILING
266
267bool CodeGenerator::ShouldGenerateLog(Expression* type) {
268 ASSERT(type != NULL);
269 if (!Logger::is_logging()) return false;
270 Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
271 if (FLAG_log_regexp) {
272 static Vector<const char> kRegexp = CStrVector("regexp");
273 if (name->IsEqualTo(kRegexp))
274 return true;
275 }
276 return false;
277}
278
279#endif
280
281
Steve Blocka7e24c12009-10-30 11:49:00 +0000282Handle<Code> CodeGenerator::ComputeCallInitialize(
283 int argc,
284 InLoopFlag in_loop) {
285 if (in_loop == IN_LOOP) {
286 // Force the creation of the corresponding stub outside loops,
287 // because it may be used when clearing the ICs later - it is
288 // possible for a series of IC transitions to lose the in-loop
289 // information, and the IC clearing code can't generate a stub
290 // that it needs so we need to ensure it is generated already.
291 ComputeCallInitialize(argc, NOT_IN_LOOP);
292 }
293 CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc, in_loop), Code);
294}
295
296
297void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
298 int length = declarations->length();
299 int globals = 0;
300 for (int i = 0; i < length; i++) {
301 Declaration* node = declarations->at(i);
302 Variable* var = node->proxy()->var();
303 Slot* slot = var->slot();
304
305 // If it was not possible to allocate the variable at compile
306 // time, we need to "declare" it at runtime to make sure it
307 // actually exists in the local context.
308 if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
309 VisitDeclaration(node);
310 } else {
311 // Count global variables and functions for later processing
312 globals++;
313 }
314 }
315
316 // Return in case of no declared global functions or variables.
317 if (globals == 0) return;
318
319 // Compute array of global variable and function declarations.
320 Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
321 for (int j = 0, i = 0; i < length; i++) {
322 Declaration* node = declarations->at(i);
323 Variable* var = node->proxy()->var();
324 Slot* slot = var->slot();
325
326 if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
327 // Skip - already processed.
328 } else {
329 array->set(j++, *(var->name()));
330 if (node->fun() == NULL) {
331 if (var->mode() == Variable::CONST) {
332 // In case this is const property use the hole.
333 array->set_the_hole(j++);
334 } else {
335 array->set_undefined(j++);
336 }
337 } else {
Steve Blockd0582a62009-12-15 09:54:21 +0000338 Handle<JSFunction> function =
339 Compiler::BuildBoilerplate(node->fun(), script(), this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 // Check for stack-overflow exception.
341 if (HasStackOverflow()) return;
342 array->set(j++, *function);
343 }
344 }
345 }
346
347 // Invoke the platform-dependent code generator to do the actual
348 // declaration the global variables and functions.
349 DeclareGlobals(array);
350}
351
352
353
354// Special cases: These 'runtime calls' manipulate the current
355// frame and are only used 1 or two places, so we generate them
356// inline instead of generating calls to them. They are used
357// for implementing Function.prototype.call() and
358// Function.prototype.apply().
359CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
360 {&CodeGenerator::GenerateIsSmi, "_IsSmi"},
361 {&CodeGenerator::GenerateIsNonNegativeSmi, "_IsNonNegativeSmi"},
362 {&CodeGenerator::GenerateIsArray, "_IsArray"},
Andrei Popescu402d9372010-02-26 13:31:12 +0000363 {&CodeGenerator::GenerateIsRegExp, "_IsRegExp"},
Steve Blocka7e24c12009-10-30 11:49:00 +0000364 {&CodeGenerator::GenerateIsConstructCall, "_IsConstructCall"},
365 {&CodeGenerator::GenerateArgumentsLength, "_ArgumentsLength"},
366 {&CodeGenerator::GenerateArgumentsAccess, "_Arguments"},
367 {&CodeGenerator::GenerateClassOf, "_ClassOf"},
368 {&CodeGenerator::GenerateValueOf, "_ValueOf"},
369 {&CodeGenerator::GenerateSetValueOf, "_SetValueOf"},
370 {&CodeGenerator::GenerateFastCharCodeAt, "_FastCharCodeAt"},
371 {&CodeGenerator::GenerateObjectEquals, "_ObjectEquals"},
372 {&CodeGenerator::GenerateLog, "_Log"},
373 {&CodeGenerator::GenerateRandomPositiveSmi, "_RandomPositiveSmi"},
Steve Blockd0582a62009-12-15 09:54:21 +0000374 {&CodeGenerator::GenerateIsObject, "_IsObject"},
375 {&CodeGenerator::GenerateIsFunction, "_IsFunction"},
Leon Clarked91b9f72010-01-27 17:25:45 +0000376 {&CodeGenerator::GenerateIsUndetectableObject, "_IsUndetectableObject"},
Steve Blockd0582a62009-12-15 09:54:21 +0000377 {&CodeGenerator::GenerateStringAdd, "_StringAdd"},
Leon Clarkee46be812010-01-19 14:06:41 +0000378 {&CodeGenerator::GenerateSubString, "_SubString"},
379 {&CodeGenerator::GenerateStringCompare, "_StringCompare"},
380 {&CodeGenerator::GenerateRegExpExec, "_RegExpExec"},
Andrei Popescu402d9372010-02-26 13:31:12 +0000381 {&CodeGenerator::GenerateNumberToString, "_NumberToString"},
382 {&CodeGenerator::GenerateMathSin, "_Math_sin"},
383 {&CodeGenerator::GenerateMathCos, "_Math_cos"},
Steve Blocka7e24c12009-10-30 11:49:00 +0000384};
385
386
387CodeGenerator::InlineRuntimeLUT* CodeGenerator::FindInlineRuntimeLUT(
388 Handle<String> name) {
389 const int entries_count =
390 sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
391 for (int i = 0; i < entries_count; i++) {
392 InlineRuntimeLUT* entry = &kInlineRuntimeLUT[i];
393 if (name->IsEqualTo(CStrVector(entry->name))) {
394 return entry;
395 }
396 }
397 return NULL;
398}
399
400
401bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
402 ZoneList<Expression*>* args = node->arguments();
403 Handle<String> name = node->name();
404 if (name->length() > 0 && name->Get(0) == '_') {
405 InlineRuntimeLUT* entry = FindInlineRuntimeLUT(name);
406 if (entry != NULL) {
407 ((*this).*(entry->method))(args);
408 return true;
409 }
410 }
411 return false;
412}
413
414
415bool CodeGenerator::PatchInlineRuntimeEntry(Handle<String> name,
416 const CodeGenerator::InlineRuntimeLUT& new_entry,
417 CodeGenerator::InlineRuntimeLUT* old_entry) {
418 InlineRuntimeLUT* entry = FindInlineRuntimeLUT(name);
419 if (entry == NULL) return false;
420 if (old_entry != NULL) {
421 old_entry->name = entry->name;
422 old_entry->method = entry->method;
423 }
424 entry->name = new_entry.name;
425 entry->method = new_entry.method;
426 return true;
427}
428
429
Steve Block3ce2e202009-11-05 08:53:23 +0000430// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
431// known result for the test expression, with no side effects.
432CodeGenerator::ConditionAnalysis CodeGenerator::AnalyzeCondition(
433 Expression* cond) {
434 if (cond == NULL) return ALWAYS_TRUE;
435
436 Literal* lit = cond->AsLiteral();
437 if (lit == NULL) return DONT_KNOW;
438
439 if (lit->IsTrue()) {
440 return ALWAYS_TRUE;
441 } else if (lit->IsFalse()) {
442 return ALWAYS_FALSE;
443 }
444
445 return DONT_KNOW;
446}
447
448
449void CodeGenerator::RecordPositions(MacroAssembler* masm, int pos) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 if (pos != RelocInfo::kNoPosition) {
Steve Block3ce2e202009-11-05 08:53:23 +0000451 masm->RecordStatementPosition(pos);
452 masm->RecordPosition(pos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 }
454}
455
456
457void CodeGenerator::CodeForFunctionPosition(FunctionLiteral* fun) {
Steve Block3ce2e202009-11-05 08:53:23 +0000458 if (FLAG_debug_info) RecordPositions(masm(), fun->start_position());
Steve Blocka7e24c12009-10-30 11:49:00 +0000459}
460
461
462void CodeGenerator::CodeForReturnPosition(FunctionLiteral* fun) {
Steve Block3ce2e202009-11-05 08:53:23 +0000463 if (FLAG_debug_info) RecordPositions(masm(), fun->end_position());
Steve Blocka7e24c12009-10-30 11:49:00 +0000464}
465
466
467void CodeGenerator::CodeForStatementPosition(Statement* stmt) {
Steve Block3ce2e202009-11-05 08:53:23 +0000468 if (FLAG_debug_info) RecordPositions(masm(), stmt->statement_pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000469}
470
Steve Blockd0582a62009-12-15 09:54:21 +0000471void CodeGenerator::CodeForDoWhileConditionPosition(DoWhileStatement* stmt) {
472 if (FLAG_debug_info) RecordPositions(masm(), stmt->condition_position());
473}
Steve Blocka7e24c12009-10-30 11:49:00 +0000474
475void CodeGenerator::CodeForSourcePosition(int pos) {
476 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
477 masm()->RecordPosition(pos);
478 }
479}
480
481
Leon Clarkee46be812010-01-19 14:06:41 +0000482const char* GenericUnaryOpStub::GetName() {
483 switch (op_) {
484 case Token::SUB:
485 return overwrite_
486 ? "GenericUnaryOpStub_SUB_Overwrite"
487 : "GenericUnaryOpStub_SUB_Alloc";
488 case Token::BIT_NOT:
489 return overwrite_
490 ? "GenericUnaryOpStub_BIT_NOT_Overwrite"
491 : "GenericUnaryOpStub_BIT_NOT_Alloc";
492 default:
493 UNREACHABLE();
494 return "<unknown>";
495 }
496}
497
498
Steve Blocka7e24c12009-10-30 11:49:00 +0000499void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
500 switch (type_) {
501 case READ_LENGTH: GenerateReadLength(masm); break;
502 case READ_ELEMENT: GenerateReadElement(masm); break;
503 case NEW_OBJECT: GenerateNewObject(masm); break;
504 }
505}
506
507
Leon Clarke4515c472010-02-03 11:58:03 +0000508int CEntryStub::MinorKey() {
509 ASSERT(result_size_ <= 2);
510#ifdef _WIN64
511 return ExitFrameModeBits::encode(mode_)
512 | IndirectResultBits::encode(result_size_ > 1);
513#else
514 return ExitFrameModeBits::encode(mode_);
515#endif
516}
517
518
Steve Blockd0582a62009-12-15 09:54:21 +0000519bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
520 Object* cache = info()->load_stub_cache();
521 if (cache->IsUndefined()) {
522 return false;
523 } else {
524 *code_out = Code::cast(cache);
525 return true;
526 }
527}
528
529
530void ApiGetterEntryStub::SetCustomCache(Code* value) {
531 info()->set_load_stub_cache(value);
532}
533
534
Steve Blocka7e24c12009-10-30 11:49:00 +0000535} } // namespace v8::internal