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