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 "codegen.h" 32 #include "compiler.h" 33 #include "cpu-profiler.h" 34 #include "debug.h" 35 #include "prettyprinter.h" 36 #include "rewriter.h" 37 #include "runtime.h" 38 #include "stub-cache.h" 39 40 namespace v8 { 41 namespace internal { 42 43 #define __ ACCESS_MASM(masm_) 44 45 #ifdef DEBUG 46 47 Comment::Comment(MacroAssembler* masm, const char* msg) 48 : masm_(masm), msg_(msg) { 49 __ RecordComment(msg); 50 } 51 52 53 Comment::~Comment() { 54 if (msg_[0] == '[') __ RecordComment("]"); 55 } 56 57 #endif // DEBUG 58 59 #undef __ 60 61 62 void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) { 63 bool print_source = false; 64 bool print_ast = false; 65 const char* ftype; 66 67 if (info->isolate()->bootstrapper()->IsActive()) { 68 print_source = FLAG_print_builtin_source; 69 print_ast = FLAG_print_builtin_ast; 70 ftype = "builtin"; 71 } else { 72 print_source = FLAG_print_source; 73 print_ast = FLAG_print_ast; 74 ftype = "user-defined"; 75 } 76 77 if (FLAG_trace_codegen || print_source || print_ast) { 78 PrintF("[generating %s code for %s function: ", kind, ftype); 79 if (info->IsStub()) { 80 const char* name = 81 CodeStub::MajorName(info->code_stub()->MajorKey(), true); 82 PrintF("%s", name == NULL ? "<unknown>" : name); 83 } else { 84 PrintF("%s", *info->function()->debug_name()->ToCString()); 85 } 86 PrintF("]\n"); 87 } 88 89 #ifdef DEBUG 90 if (!info->IsStub() && print_source) { 91 PrintF("--- Source from AST ---\n%s\n", 92 PrettyPrinter().PrintProgram(info->function())); 93 } 94 95 if (!info->IsStub() && print_ast) { 96 PrintF("--- AST ---\n%s\n", 97 AstPrinter().PrintProgram(info->function())); 98 } 99 #endif // DEBUG 100 } 101 102 103 Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm, 104 Code::Flags flags, 105 CompilationInfo* info) { 106 Isolate* isolate = info->isolate(); 107 108 // Allocate and install the code. 109 CodeDesc desc; 110 bool is_crankshafted = 111 Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION || 112 info->IsStub(); 113 masm->GetCode(&desc); 114 Handle<Code> code = 115 isolate->factory()->NewCode(desc, flags, masm->CodeObject(), 116 false, is_crankshafted); 117 if (!code.is_null()) { 118 isolate->counters()->total_compiled_code_size()->Increment( 119 code->instruction_size()); 120 code->set_prologue_offset(info->prologue_offset()); 121 } 122 return code; 123 } 124 125 126 void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) { 127 #ifdef ENABLE_DISASSEMBLER 128 AllowDeferredHandleDereference allow_deference_for_print_code; 129 bool print_code = Isolate::Current()->bootstrapper()->IsActive() 130 ? FLAG_print_builtin_code 131 : (FLAG_print_code || 132 (info->IsStub() && FLAG_print_code_stubs) || 133 (info->IsOptimizing() && FLAG_print_opt_code)); 134 if (print_code) { 135 // Print the source code if available. 136 FunctionLiteral* function = info->function(); 137 if (code->kind() == Code::OPTIMIZED_FUNCTION) { 138 Handle<Script> script = info->script(); 139 if (!script->IsUndefined() && !script->source()->IsUndefined()) { 140 PrintF("--- Raw source ---\n"); 141 ConsStringIteratorOp op; 142 StringCharacterStream stream(String::cast(script->source()), 143 &op, 144 function->start_position()); 145 // fun->end_position() points to the last character in the stream. We 146 // need to compensate by adding one to calculate the length. 147 int source_len = 148 function->end_position() - function->start_position() + 1; 149 for (int i = 0; i < source_len; i++) { 150 if (stream.HasMore()) PrintF("%c", stream.GetNext()); 151 } 152 PrintF("\n\n"); 153 } 154 } 155 if (info->IsOptimizing()) { 156 if (FLAG_print_unopt_code) { 157 PrintF("--- Unoptimized code ---\n"); 158 info->closure()->shared()->code()->Disassemble( 159 *function->debug_name()->ToCString()); 160 } 161 PrintF("--- Optimized code ---\n"); 162 } else { 163 PrintF("--- Code ---\n"); 164 } 165 if (info->IsStub()) { 166 CodeStub::Major major_key = info->code_stub()->MajorKey(); 167 code->Disassemble(CodeStub::MajorName(major_key, false)); 168 } else { 169 code->Disassemble(*function->debug_name()->ToCString()); 170 } 171 } 172 #endif // ENABLE_DISASSEMBLER 173 } 174 175 176 bool CodeGenerator::ShouldGenerateLog(Expression* type) { 177 ASSERT(type != NULL); 178 Isolate* isolate = Isolate::Current(); 179 if (!isolate->logger()->is_logging() && 180 !isolate->cpu_profiler()->is_profiling()) { 181 return false; 182 } 183 Handle<String> name = Handle<String>::cast(type->AsLiteral()->value()); 184 if (FLAG_log_regexp) { 185 if (name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("regexp"))) 186 return true; 187 } 188 return false; 189 } 190 191 192 bool CodeGenerator::RecordPositions(MacroAssembler* masm, 193 int pos, 194 bool right_here) { 195 if (pos != RelocInfo::kNoPosition) { 196 masm->positions_recorder()->RecordStatementPosition(pos); 197 masm->positions_recorder()->RecordPosition(pos); 198 if (right_here) { 199 return masm->positions_recorder()->WriteRecordedPositions(); 200 } 201 } 202 return false; 203 } 204 205 206 void ArgumentsAccessStub::Generate(MacroAssembler* masm) { 207 switch (type_) { 208 case READ_ELEMENT: 209 GenerateReadElement(masm); 210 break; 211 case NEW_NON_STRICT_FAST: 212 GenerateNewNonStrictFast(masm); 213 break; 214 case NEW_NON_STRICT_SLOW: 215 GenerateNewNonStrictSlow(masm); 216 break; 217 case NEW_STRICT: 218 GenerateNewStrict(masm); 219 break; 220 } 221 } 222 223 224 int CEntryStub::MinorKey() { 225 int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0; 226 ASSERT(result_size_ == 1 || result_size_ == 2); 227 #ifdef _WIN64 228 return result | ((result_size_ == 1) ? 0 : 2); 229 #else 230 return result; 231 #endif 232 } 233 234 235 } } // namespace v8::internal 236