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 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
31 #include "debug.h" | 31 #include "debug.h" |
32 #include "fast-codegen.h" | 32 #include "fast-codegen.h" |
| 33 #include "parser.h" |
33 | 34 |
34 namespace v8 { | 35 namespace v8 { |
35 namespace internal { | 36 namespace internal { |
36 | 37 |
37 #define __ ACCESS_MASM(masm_) | 38 #define __ ACCESS_MASM(masm_) |
38 | 39 |
39 // Generate code for a JS function. On entry to the function the receiver | 40 // Generate code for a JS function. On entry to the function the receiver |
40 // and arguments have been pushed on the stack left to right, with the | 41 // and arguments have been pushed on the stack left to right, with the |
41 // return address on top of them. The actual argument count matches the | 42 // return address on top of them. The actual argument count matches the |
42 // formal parameter count expected by the function. | 43 // formal parameter count expected by the function. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 for (int i = 0; i < kPadding; ++i) { | 102 for (int i = 0; i < kPadding; ++i) { |
102 masm_->int3(); | 103 masm_->int3(); |
103 } | 104 } |
104 #endif | 105 #endif |
105 } | 106 } |
106 } | 107 } |
107 | 108 |
108 | 109 |
109 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 110 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
110 // Call the runtime to declare the globals. | 111 // Call the runtime to declare the globals. |
| 112 __ push(rsi); // The context is the first argument. |
111 __ Push(pairs); | 113 __ Push(pairs); |
112 __ push(rsi); // The context is the second argument. | |
113 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); | 114 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); |
114 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 115 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
115 // Return value is ignored. | 116 // Return value is ignored. |
116 } | 117 } |
117 | 118 |
118 | 119 |
119 void FastCodeGenerator::VisitBlock(Block* stmt) { | 120 void FastCodeGenerator::VisitBlock(Block* stmt) { |
120 Comment cmnt(masm_, "[ Block"); | 121 Comment cmnt(masm_, "[ Block"); |
121 SetStatementPosition(stmt); | 122 SetStatementPosition(stmt); |
122 VisitStatements(stmt->statements()); | 123 VisitStatements(stmt->statements()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 168 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
168 Comment cmnt(masm_, "[ FunctionLiteral"); | 169 Comment cmnt(masm_, "[ FunctionLiteral"); |
169 | 170 |
170 // Build the function boilerplate and instantiate it. | 171 // Build the function boilerplate and instantiate it. |
171 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); | 172 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); |
172 if (HasStackOverflow()) return; | 173 if (HasStackOverflow()) return; |
173 | 174 |
174 ASSERT(boilerplate->IsBoilerplate()); | 175 ASSERT(boilerplate->IsBoilerplate()); |
175 | 176 |
176 // Create a new closure. | 177 // Create a new closure. |
| 178 __ push(rsi); |
177 __ Push(boilerplate); | 179 __ Push(boilerplate); |
178 __ push(rsi); | |
179 __ CallRuntime(Runtime::kNewClosure, 2); | 180 __ CallRuntime(Runtime::kNewClosure, 2); |
180 | 181 |
181 if (expr->location().is_temporary()) { | 182 if (expr->location().is_temporary()) { |
182 __ push(rax); | 183 __ push(rax); |
183 } else { | 184 } else { |
184 ASSERT(expr->location().is_nowhere()); | 185 ASSERT(expr->location().is_nowhere()); |
185 } | 186 } |
186 } | 187 } |
187 | 188 |
188 | 189 |
(...skipping 10 matching lines...) Expand all Loading... |
199 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 200 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
200 | 201 |
201 // A test rax instruction following the call is used by the IC to | 202 // A test rax instruction following the call is used by the IC to |
202 // indicate that the inobject property case was inlined. Ensure there | 203 // indicate that the inobject property case was inlined. Ensure there |
203 // is no test rax instruction here. | 204 // is no test rax instruction here. |
204 if (expr->location().is_temporary()) { | 205 if (expr->location().is_temporary()) { |
205 // Replace the global object with the result. | 206 // Replace the global object with the result. |
206 __ movq(Operand(rsp, 0), rax); | 207 __ movq(Operand(rsp, 0), rax); |
207 } else { | 208 } else { |
208 ASSERT(expr->location().is_nowhere()); | 209 ASSERT(expr->location().is_nowhere()); |
209 __ pop(rax); | 210 __ addq(rsp, Immediate(kPointerSize)); |
210 } | 211 } |
211 | 212 |
212 } else { | 213 } else { |
213 Comment cmnt(masm_, "Stack slot"); | 214 Comment cmnt(masm_, "Stack slot"); |
214 Slot* slot = rewrite->AsSlot(); | 215 Slot* slot = rewrite->AsSlot(); |
215 ASSERT(slot != NULL); | 216 ASSERT(slot != NULL); |
216 if (expr->location().is_temporary()) { | 217 if (expr->location().is_temporary()) { |
217 __ push(Operand(rbp, SlotOffset(slot))); | 218 __ push(Operand(rbp, SlotOffset(slot))); |
218 } else { | 219 } else { |
219 ASSERT(expr->location().is_nowhere()); | 220 ASSERT(expr->location().is_nowhere()); |
220 } | 221 } |
221 } | 222 } |
222 } | 223 } |
223 | 224 |
224 | 225 |
| 226 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 227 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 228 Label make_clone; |
| 229 |
| 230 // Fetch the function's literals array. |
| 231 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 232 __ movq(rbx, FieldOperand(rbx, JSFunction::kLiteralsOffset)); |
| 233 // Check if the literal's boilerplate has been instantiated. |
| 234 int offset = |
| 235 FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); |
| 236 __ movq(rax, FieldOperand(rbx, offset)); |
| 237 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 238 __ j(not_equal, &make_clone); |
| 239 |
| 240 // Instantiate the boilerplate. |
| 241 __ push(rbx); |
| 242 __ Push(Smi::FromInt(expr->literal_index())); |
| 243 __ Push(expr->literals()); |
| 244 __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); |
| 245 |
| 246 __ bind(&make_clone); |
| 247 // Clone the boilerplate. |
| 248 __ push(rax); |
| 249 if (expr->depth() > 1) { |
| 250 __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); |
| 251 } else { |
| 252 __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); |
| 253 } |
| 254 |
| 255 bool result_saved = false; // Is the result saved to the stack? |
| 256 |
| 257 // Emit code to evaluate all the non-constant subexpressions and to store |
| 258 // them into the newly cloned array. |
| 259 ZoneList<Expression*>* subexprs = expr->values(); |
| 260 for (int i = 0, len = subexprs->length(); i < len; i++) { |
| 261 Expression* subexpr = subexprs->at(i); |
| 262 // If the subexpression is a literal or a simple materialized literal it |
| 263 // is already set in the cloned array. |
| 264 if (subexpr->AsLiteral() != NULL || |
| 265 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
| 266 continue; |
| 267 } |
| 268 |
| 269 if (!result_saved) { |
| 270 __ push(rax); |
| 271 result_saved = true; |
| 272 } |
| 273 Visit(subexpr); |
| 274 ASSERT(subexpr->location().is_temporary()); |
| 275 |
| 276 // Store the subexpression value in the array's elements. |
| 277 __ pop(rax); // Subexpression value. |
| 278 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. |
| 279 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); |
| 280 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 281 __ movq(FieldOperand(rbx, offset), rax); |
| 282 |
| 283 // Update the write barrier for the array store. |
| 284 __ RecordWrite(rbx, offset, rax, rcx); |
| 285 } |
| 286 |
| 287 Location destination = expr->location(); |
| 288 if (destination.is_nowhere() && result_saved) { |
| 289 __ addq(rsp, Immediate(kPointerSize)); |
| 290 } else if (destination.is_temporary() && !result_saved) { |
| 291 __ push(rax); |
| 292 } |
| 293 } |
| 294 |
| 295 |
225 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 296 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
226 Comment cmnt(masm_, "[ Assignment"); | 297 Comment cmnt(masm_, "[ Assignment"); |
227 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 298 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
228 Expression* rhs = expr->value(); | 299 Expression* rhs = expr->value(); |
229 Visit(rhs); | 300 Visit(rhs); |
230 | 301 |
231 // Left-hand side can only be a global or a (parameter or local) slot. | 302 // Left-hand side can only be a global or a (parameter or local) slot. |
232 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 303 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
233 ASSERT(var != NULL); | 304 ASSERT(var != NULL); |
234 ASSERT(var->is_global() || var->slot() != NULL); | 305 ASSERT(var->is_global() || var->slot() != NULL); |
(...skipping 17 matching lines...) Expand all Loading... |
252 __ Move(rax, rhs->AsLiteral()->handle()); | 323 __ Move(rax, rhs->AsLiteral()->handle()); |
253 } | 324 } |
254 __ Move(rcx, var->name()); | 325 __ Move(rcx, var->name()); |
255 __ push(CodeGenerator::GlobalObject()); | 326 __ push(CodeGenerator::GlobalObject()); |
256 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 327 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
257 __ Call(ic, RelocInfo::CODE_TARGET); | 328 __ Call(ic, RelocInfo::CODE_TARGET); |
258 // Overwrite the global object on the stack with the result if needed. | 329 // Overwrite the global object on the stack with the result if needed. |
259 if (destination.is_temporary()) { | 330 if (destination.is_temporary()) { |
260 __ movq(Operand(rsp, 0), rax); | 331 __ movq(Operand(rsp, 0), rax); |
261 } else { | 332 } else { |
262 __ pop(rax); | 333 __ addq(rsp, Immediate(kPointerSize)); |
263 } | 334 } |
264 } else { | 335 } else { |
265 if (source.is_temporary()) { | 336 if (source.is_temporary()) { |
266 if (destination.is_temporary()) { | 337 if (destination.is_temporary()) { |
267 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary | 338 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary |
268 // on the stack. | 339 // on the stack. |
269 __ movq(kScratchRegister, Operand(rsp, 0)); | 340 __ movq(kScratchRegister, Operand(rsp, 0)); |
270 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | 341 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
271 } else { | 342 } else { |
272 ASSERT(destination.is_nowhere()); | 343 ASSERT(destination.is_nowhere()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 385 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
315 NOT_IN_LOOP); | 386 NOT_IN_LOOP); |
316 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 387 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
317 // Restore context register. | 388 // Restore context register. |
318 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 389 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
319 // Discard the function left on TOS. | 390 // Discard the function left on TOS. |
320 if (expr->location().is_temporary()) { | 391 if (expr->location().is_temporary()) { |
321 __ movq(Operand(rsp, 0), rax); | 392 __ movq(Operand(rsp, 0), rax); |
322 } else { | 393 } else { |
323 ASSERT(expr->location().is_nowhere()); | 394 ASSERT(expr->location().is_nowhere()); |
324 __ pop(rax); | 395 __ addq(rsp, Immediate(kPointerSize)); |
325 } | 396 } |
326 } | 397 } |
327 | 398 |
328 | 399 |
329 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 400 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
330 Comment cmnt(masm_, "[ CallRuntime"); | 401 Comment cmnt(masm_, "[ CallRuntime"); |
331 ZoneList<Expression*>* args = expr->arguments(); | 402 ZoneList<Expression*>* args = expr->arguments(); |
332 Runtime::Function* function = expr->function(); | 403 Runtime::Function* function = expr->function(); |
333 | 404 |
334 ASSERT(function != NULL); | 405 ASSERT(function != NULL); |
(...skipping 12 matching lines...) Expand all Loading... |
347 __ CallRuntime(function, arg_count); | 418 __ CallRuntime(function, arg_count); |
348 if (expr->location().is_temporary()) { | 419 if (expr->location().is_temporary()) { |
349 __ push(rax); | 420 __ push(rax); |
350 } else { | 421 } else { |
351 ASSERT(expr->location().is_nowhere()); | 422 ASSERT(expr->location().is_nowhere()); |
352 } | 423 } |
353 } | 424 } |
354 | 425 |
355 | 426 |
356 } } // namespace v8::internal | 427 } } // namespace v8::internal |
OLD | NEW |