OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 | 67 |
68 { Comment cmnt(masm_, "[ Stack check"); | 68 { Comment cmnt(masm_, "[ Stack check"); |
69 Label ok; | 69 Label ok; |
70 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 70 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
71 __ j(above_equal, &ok); | 71 __ j(above_equal, &ok); |
72 StackCheckStub stub; | 72 StackCheckStub stub; |
73 __ CallStub(&stub); | 73 __ CallStub(&stub); |
74 __ bind(&ok); | 74 __ bind(&ok); |
75 } | 75 } |
76 | 76 |
| 77 { Comment cmnt(masm_, "[ Declarations"); |
| 78 VisitDeclarations(fun->scope()->declarations()); |
| 79 } |
| 80 |
77 { Comment cmnt(masm_, "[ Body"); | 81 { Comment cmnt(masm_, "[ Body"); |
78 VisitStatements(fun->body()); | 82 VisitStatements(fun->body()); |
79 } | 83 } |
80 | 84 |
81 { Comment cmnt(masm_, "[ return <undefined>;"); | 85 { Comment cmnt(masm_, "[ return <undefined>;"); |
82 // Emit a 'return undefined' in case control fell off the end of the | 86 // Emit a 'return undefined' in case control fell off the end of the |
83 // body. | 87 // body. |
84 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 88 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
85 SetReturnPosition(fun); | 89 SetReturnPosition(fun); |
86 __ RecordJSReturn(); | 90 __ RecordJSReturn(); |
87 // Do not use the leave instruction here because it is too short to | 91 // Do not use the leave instruction here because it is too short to |
88 // patch with the code required by the debugger. | 92 // patch with the code required by the debugger. |
89 __ movq(rsp, rbp); | 93 __ movq(rsp, rbp); |
90 __ pop(rbp); | 94 __ pop(rbp); |
91 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); | 95 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); |
92 #ifdef ENABLE_DEBUGGER_SUPPORT | 96 #ifdef ENABLE_DEBUGGER_SUPPORT |
93 // Add padding that will be overwritten by a debugger breakpoint. We | 97 // Add padding that will be overwritten by a debugger breakpoint. We |
94 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 | 98 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 |
95 // (3 + 1 + 3). | 99 // (3 + 1 + 3). |
96 const int kPadding = Debug::kX64JSReturnSequenceLength - 7; | 100 const int kPadding = Debug::kX64JSReturnSequenceLength - 7; |
97 for (int i = 0; i < kPadding; ++i) { | 101 for (int i = 0; i < kPadding; ++i) { |
98 masm_->int3(); | 102 masm_->int3(); |
99 } | 103 } |
100 #endif | 104 #endif |
101 } | 105 } |
102 } | 106 } |
103 | 107 |
104 | 108 |
| 109 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 110 // Call the runtime to declare the globals. |
| 111 __ Push(pairs); |
| 112 __ push(rsi); // The context is the second argument. |
| 113 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); |
| 114 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 115 // Return value is ignored. |
| 116 } |
| 117 |
| 118 |
| 119 void FastCodeGenerator::VisitBlock(Block* stmt) { |
| 120 Comment cmnt(masm_, "[ Block"); |
| 121 SetStatementPosition(stmt); |
| 122 VisitStatements(stmt->statements()); |
| 123 } |
| 124 |
| 125 |
105 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 126 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
106 Comment cmnt(masm_, "[ ExpressionStatement"); | 127 Comment cmnt(masm_, "[ ExpressionStatement"); |
107 SetStatementPosition(stmt); | 128 SetStatementPosition(stmt); |
108 Visit(stmt->expression()); | 129 Visit(stmt->expression()); |
109 } | 130 } |
110 | 131 |
111 | 132 |
112 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 133 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
113 Comment cmnt(masm_, "[ ReturnStatement"); | 134 Comment cmnt(masm_, "[ ReturnStatement"); |
114 SetStatementPosition(stmt); | 135 SetStatementPosition(stmt); |
(...skipping 21 matching lines...) Expand all Loading... |
136 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 | 157 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 |
137 // (3 + 1 + 3). | 158 // (3 + 1 + 3). |
138 const int kPadding = Debug::kX64JSReturnSequenceLength - 7; | 159 const int kPadding = Debug::kX64JSReturnSequenceLength - 7; |
139 for (int i = 0; i < kPadding; ++i) { | 160 for (int i = 0; i < kPadding; ++i) { |
140 masm_->int3(); | 161 masm_->int3(); |
141 } | 162 } |
142 #endif | 163 #endif |
143 } | 164 } |
144 | 165 |
145 | 166 |
| 167 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 168 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 169 |
| 170 // Build the function boilerplate and instantiate it. |
| 171 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); |
| 172 if (HasStackOverflow()) return; |
| 173 |
| 174 ASSERT(boilerplate->IsBoilerplate()); |
| 175 |
| 176 // Create a new closure. |
| 177 __ Push(boilerplate); |
| 178 __ push(rsi); |
| 179 __ CallRuntime(Runtime::kNewClosure, 2); |
| 180 |
| 181 if (expr->location().is_temporary()) { |
| 182 __ push(rax); |
| 183 } else { |
| 184 ASSERT(expr->location().is_nowhere()); |
| 185 } |
| 186 } |
| 187 |
| 188 |
146 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 189 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
147 Comment cmnt(masm_, "[ VariableProxy"); | 190 Comment cmnt(masm_, "[ VariableProxy"); |
148 Expression* rewrite = expr->var()->rewrite(); | 191 Expression* rewrite = expr->var()->rewrite(); |
149 ASSERT(rewrite != NULL); | 192 ASSERT(rewrite != NULL); |
150 | 193 |
151 Slot* slot = rewrite->AsSlot(); | 194 Slot* slot = rewrite->AsSlot(); |
152 ASSERT(slot != NULL); | 195 ASSERT(slot != NULL); |
153 { Comment cmnt(masm_, "[ Slot"); | 196 { Comment cmnt(masm_, "[ Slot"); |
154 if (expr->location().is_temporary()) { | 197 if (expr->location().is_temporary()) { |
155 __ push(Operand(rbp, SlotOffset(slot))); | 198 __ push(Operand(rbp, SlotOffset(slot))); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | 263 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
221 if (destination.is_temporary()) { | 264 if (destination.is_temporary()) { |
222 // Case 'temp <- (var = constant)'. Save result. | 265 // Case 'temp <- (var = constant)'. Save result. |
223 __ push(kScratchRegister); | 266 __ push(kScratchRegister); |
224 } | 267 } |
225 } | 268 } |
226 } | 269 } |
227 } | 270 } |
228 | 271 |
229 | 272 |
| 273 void FastCodeGenerator::VisitCall(Call* expr) { |
| 274 Expression* fun = expr->expression(); |
| 275 ZoneList<Expression*>* args = expr->arguments(); |
| 276 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 277 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
| 278 ASSERT(!var->is_possibly_eval()); |
| 279 |
| 280 __ Push(var->name()); |
| 281 // Push global object (receiver). |
| 282 __ push(CodeGenerator::GlobalObject()); |
| 283 int arg_count = args->length(); |
| 284 for (int i = 0; i < arg_count; i++) { |
| 285 Visit(args->at(i)); |
| 286 ASSERT(!args->at(i)->location().is_nowhere()); |
| 287 if (args->at(i)->location().is_constant()) { |
| 288 ASSERT(args->at(i)->AsLiteral() != NULL); |
| 289 __ Push(args->at(i)->AsLiteral()->handle()); |
| 290 } |
| 291 } |
| 292 // Record source position for debugger |
| 293 SetSourcePosition(expr->position()); |
| 294 // Call the IC initialization code. |
| 295 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 296 NOT_IN_LOOP); |
| 297 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 298 // Restore context register. |
| 299 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 300 // Discard the function left on TOS. |
| 301 if (expr->location().is_temporary()) { |
| 302 __ movq(Operand(rsp, 0), rax); |
| 303 } else { |
| 304 ASSERT(expr->location().is_nowhere()); |
| 305 __ pop(rax); |
| 306 } |
| 307 } |
| 308 |
| 309 |
| 310 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 311 Comment cmnt(masm_, "[ CallRuntime"); |
| 312 ZoneList<Expression*>* args = expr->arguments(); |
| 313 Runtime::Function* function = expr->function(); |
| 314 |
| 315 ASSERT(function != NULL); |
| 316 |
| 317 // Push the arguments ("left-to-right"). |
| 318 int arg_count = args->length(); |
| 319 for (int i = 0; i < arg_count; i++) { |
| 320 Visit(args->at(i)); |
| 321 ASSERT(!args->at(i)->location().is_nowhere()); |
| 322 if (args->at(i)->location().is_constant()) { |
| 323 ASSERT(args->at(i)->AsLiteral() != NULL); |
| 324 __ Push(args->at(i)->AsLiteral()->handle()); |
| 325 } |
| 326 } |
| 327 |
| 328 __ CallRuntime(function, arg_count); |
| 329 if (expr->location().is_temporary()) { |
| 330 __ push(rax); |
| 331 } else { |
| 332 ASSERT(expr->location().is_nowhere()); |
| 333 } |
| 334 } |
| 335 |
| 336 |
230 } } // namespace v8::internal | 337 } } // namespace v8::internal |
OLD | NEW |