| 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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 // patch with the code required by the debugger. | 103 // patch with the code required by the debugger. |
| 104 __ mov(esp, ebp); | 104 __ mov(esp, ebp); |
| 105 __ pop(ebp); | 105 __ pop(ebp); |
| 106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); | 106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); |
| 107 } | 107 } |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 void FastCodeGenerator::Move(Location destination, Slot* source) { | 111 void FastCodeGenerator::Move(Location destination, Slot* source) { |
| 112 switch (destination.type()) { | 112 switch (destination.type()) { |
| 113 case Location::NOWHERE: | 113 case Location::UNINITIALIZED: |
| 114 UNREACHABLE(); |
| 115 case Location::EFFECT: |
| 114 break; | 116 break; |
| 115 case Location::TEMP: | 117 case Location::VALUE: |
| 116 __ push(Operand(ebp, SlotOffset(source))); | 118 __ push(Operand(ebp, SlotOffset(source))); |
| 117 break; | 119 break; |
| 118 } | 120 } |
| 119 } | 121 } |
| 120 | 122 |
| 121 | 123 |
| 122 void FastCodeGenerator::Move(Location destination, Literal* expr) { | 124 void FastCodeGenerator::Move(Location destination, Literal* expr) { |
| 123 switch (destination.type()) { | 125 switch (destination.type()) { |
| 124 case Location::NOWHERE: | 126 case Location::UNINITIALIZED: |
| 127 UNREACHABLE(); |
| 128 case Location::EFFECT: |
| 125 break; | 129 break; |
| 126 case Location::TEMP: | 130 case Location::VALUE: |
| 127 __ push(Immediate(expr->handle())); | 131 __ push(Immediate(expr->handle())); |
| 128 break; | 132 break; |
| 129 } | 133 } |
| 130 } | 134 } |
| 131 | 135 |
| 132 | 136 |
| 133 void FastCodeGenerator::Move(Slot* destination, Location source) { | 137 void FastCodeGenerator::Move(Slot* destination, Location source) { |
| 134 switch (source.type()) { | 138 switch (source.type()) { |
| 135 case Location::NOWHERE: | 139 case Location::UNINITIALIZED: // Fall through. |
| 140 case Location::EFFECT: |
| 136 UNREACHABLE(); | 141 UNREACHABLE(); |
| 137 case Location::TEMP: | 142 case Location::VALUE: |
| 138 __ pop(Operand(ebp, SlotOffset(destination))); | 143 __ pop(Operand(ebp, SlotOffset(destination))); |
| 139 break; | 144 break; |
| 140 } | 145 } |
| 141 } | 146 } |
| 142 | 147 |
| 143 | 148 |
| 144 void FastCodeGenerator::DropAndMove(Location destination, Register source) { | 149 void FastCodeGenerator::DropAndMove(Location destination, Register source) { |
| 145 switch (destination.type()) { | 150 switch (destination.type()) { |
| 146 case Location::NOWHERE: | 151 case Location::UNINITIALIZED: |
| 152 UNREACHABLE(); |
| 153 case Location::EFFECT: |
| 147 __ add(Operand(esp), Immediate(kPointerSize)); | 154 __ add(Operand(esp), Immediate(kPointerSize)); |
| 148 break; | 155 break; |
| 149 case Location::TEMP: | 156 case Location::VALUE: |
| 150 __ mov(Operand(esp, 0), source); | 157 __ mov(Operand(esp, 0), source); |
| 151 break; | 158 break; |
| 152 } | 159 } |
| 153 } | 160 } |
| 154 | 161 |
| 155 | 162 |
| 156 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 163 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 157 // Call the runtime to declare the globals. | 164 // Call the runtime to declare the globals. |
| 158 __ push(esi); // The context is the first argument. | 165 __ push(esi); // The context is the first argument. |
| 159 __ push(Immediate(pairs)); | 166 __ push(Immediate(pairs)); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 __ nop(); | 231 __ nop(); |
| 225 | 232 |
| 226 DropAndMove(expr->location(), eax); | 233 DropAndMove(expr->location(), eax); |
| 227 } else { | 234 } else { |
| 228 Comment cmnt(masm_, "Stack slot"); | 235 Comment cmnt(masm_, "Stack slot"); |
| 229 Move(expr->location(), rewrite->AsSlot()); | 236 Move(expr->location(), rewrite->AsSlot()); |
| 230 } | 237 } |
| 231 } | 238 } |
| 232 | 239 |
| 233 | 240 |
| 241 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 242 Comment cmnt(masm_, "[ RegExp Literal"); |
| 243 Label done; |
| 244 // Registers will be used as follows: |
| 245 // edi = JS function. |
| 246 // ebx = literals array. |
| 247 // eax = regexp literal. |
| 248 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 249 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 250 int literal_offset = |
| 251 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 252 __ mov(eax, FieldOperand(ebx, literal_offset)); |
| 253 __ cmp(eax, Factory::undefined_value()); |
| 254 __ j(not_equal, &done); |
| 255 // Create regexp literal using runtime function |
| 256 // Result will be in eax. |
| 257 __ push(ebx); |
| 258 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 259 __ push(Immediate(expr->pattern())); |
| 260 __ push(Immediate(expr->flags())); |
| 261 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 262 // Label done: |
| 263 __ bind(&done); |
| 264 Move(expr->location(), eax); |
| 265 } |
| 266 |
| 267 |
| 234 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 268 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 235 Comment cmnt(masm_, "[ ObjectLiteral"); | 269 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 236 Label exists; | 270 Label exists; |
| 237 // Registers will be used as follows: | 271 // Registers will be used as follows: |
| 238 // edi = JS function. | 272 // edi = JS function. |
| 239 // ebx = literals array. | 273 // ebx = literals array. |
| 240 // eax = boilerplate | 274 // eax = boilerplate |
| 241 | 275 |
| 242 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 276 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 243 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 277 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 __ mov(ecx, Immediate(key->handle())); | 322 __ mov(ecx, Immediate(key->handle())); |
| 289 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 323 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 290 __ call(ic, RelocInfo::CODE_TARGET); | 324 __ call(ic, RelocInfo::CODE_TARGET); |
| 291 // StoreIC leaves the receiver on the stack. | 325 // StoreIC leaves the receiver on the stack. |
| 292 break; | 326 break; |
| 293 } | 327 } |
| 294 // fall through | 328 // fall through |
| 295 case ObjectLiteral::Property::PROTOTYPE: | 329 case ObjectLiteral::Property::PROTOTYPE: |
| 296 __ push(eax); | 330 __ push(eax); |
| 297 Visit(key); | 331 Visit(key); |
| 298 ASSERT(key->location().is_temporary()); | 332 ASSERT(key->location().is_value()); |
| 299 Visit(value); | 333 Visit(value); |
| 300 ASSERT(value->location().is_temporary()); | 334 ASSERT(value->location().is_value()); |
| 301 __ CallRuntime(Runtime::kSetProperty, 3); | 335 __ CallRuntime(Runtime::kSetProperty, 3); |
| 302 __ mov(eax, Operand(esp, 0)); // Restore result into eax. | 336 __ mov(eax, Operand(esp, 0)); // Restore result into eax. |
| 303 break; | 337 break; |
| 304 case ObjectLiteral::Property::SETTER: // fall through | 338 case ObjectLiteral::Property::SETTER: // fall through |
| 305 case ObjectLiteral::Property::GETTER: | 339 case ObjectLiteral::Property::GETTER: |
| 306 __ push(eax); | 340 __ push(eax); |
| 307 Visit(key); | 341 Visit(key); |
| 308 ASSERT(key->location().is_temporary()); | 342 ASSERT(key->location().is_value()); |
| 309 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? | 343 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? |
| 310 Smi::FromInt(1) : | 344 Smi::FromInt(1) : |
| 311 Smi::FromInt(0))); | 345 Smi::FromInt(0))); |
| 312 Visit(value); | 346 Visit(value); |
| 313 ASSERT(value->location().is_temporary()); | 347 ASSERT(value->location().is_value()); |
| 314 __ CallRuntime(Runtime::kDefineAccessor, 4); | 348 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 315 __ mov(eax, Operand(esp, 0)); // Restore result into eax. | 349 __ mov(eax, Operand(esp, 0)); // Restore result into eax. |
| 316 break; | 350 break; |
| 317 default: UNREACHABLE(); | 351 default: UNREACHABLE(); |
| 318 } | 352 } |
| 319 } | 353 } |
| 320 switch (expr->location().type()) { | 354 switch (expr->location().type()) { |
| 321 case Location::NOWHERE: | 355 case Location::UNINITIALIZED: |
| 356 UNREACHABLE(); |
| 357 case Location::EFFECT: |
| 322 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 358 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); |
| 323 break; | 359 break; |
| 324 case Location::TEMP: | 360 case Location::VALUE: |
| 325 if (!result_saved) __ push(eax); | 361 if (!result_saved) __ push(eax); |
| 326 break; | 362 break; |
| 327 } | 363 } |
| 328 } | 364 } |
| 329 | 365 |
| 330 | 366 |
| 331 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | |
| 332 Comment cmnt(masm_, "[ RegExp Literal"); | |
| 333 Label done; | |
| 334 // Registers will be used as follows: | |
| 335 // edi = JS function. | |
| 336 // ebx = literals array. | |
| 337 // eax = regexp literal. | |
| 338 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | |
| 339 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | |
| 340 int literal_offset = | |
| 341 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | |
| 342 __ mov(eax, FieldOperand(ebx, literal_offset)); | |
| 343 __ cmp(eax, Factory::undefined_value()); | |
| 344 __ j(not_equal, &done); | |
| 345 // Create regexp literal using runtime function | |
| 346 // Result will be in eax. | |
| 347 __ push(ebx); | |
| 348 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | |
| 349 __ push(Immediate(expr->pattern())); | |
| 350 __ push(Immediate(expr->flags())); | |
| 351 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | |
| 352 // Label done: | |
| 353 __ bind(&done); | |
| 354 Move(expr->location(), eax); | |
| 355 } | |
| 356 | |
| 357 | |
| 358 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 367 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 359 Comment cmnt(masm_, "[ ArrayLiteral"); | 368 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 360 Label make_clone; | 369 Label make_clone; |
| 361 | 370 |
| 362 // Fetch the function's literals array. | 371 // Fetch the function's literals array. |
| 363 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 372 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 364 __ mov(ebx, FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 373 __ mov(ebx, FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
| 365 // Check if the literal's boilerplate has been instantiated. | 374 // Check if the literal's boilerplate has been instantiated. |
| 366 int offset = | 375 int offset = |
| 367 FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); | 376 FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 396 if (subexpr->AsLiteral() != NULL || | 405 if (subexpr->AsLiteral() != NULL || |
| 397 CompileTimeValue::IsCompileTimeValue(subexpr)) { | 406 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
| 398 continue; | 407 continue; |
| 399 } | 408 } |
| 400 | 409 |
| 401 if (!result_saved) { | 410 if (!result_saved) { |
| 402 __ push(eax); | 411 __ push(eax); |
| 403 result_saved = true; | 412 result_saved = true; |
| 404 } | 413 } |
| 405 Visit(subexpr); | 414 Visit(subexpr); |
| 406 ASSERT(subexpr->location().is_temporary()); | 415 ASSERT(subexpr->location().is_value()); |
| 407 | 416 |
| 408 // Store the subexpression value in the array's elements. | 417 // Store the subexpression value in the array's elements. |
| 409 __ pop(eax); // Subexpression value. | 418 __ pop(eax); // Subexpression value. |
| 410 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. | 419 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. |
| 411 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); | 420 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
| 412 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 421 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 413 __ mov(FieldOperand(ebx, offset), eax); | 422 __ mov(FieldOperand(ebx, offset), eax); |
| 414 | 423 |
| 415 // Update the write barrier for the array store. | 424 // Update the write barrier for the array store. |
| 416 __ RecordWrite(ebx, offset, eax, ecx); | 425 __ RecordWrite(ebx, offset, eax, ecx); |
| 417 } | 426 } |
| 418 | 427 |
| 419 switch (expr->location().type()) { | 428 switch (expr->location().type()) { |
| 420 case Location::NOWHERE: | 429 case Location::UNINITIALIZED: |
| 430 UNREACHABLE(); |
| 431 case Location::EFFECT: |
| 421 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 432 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); |
| 422 break; | 433 break; |
| 423 case Location::TEMP: | 434 case Location::VALUE: |
| 424 if (!result_saved) __ push(eax); | 435 if (!result_saved) __ push(eax); |
| 425 break; | 436 break; |
| 426 } | 437 } |
| 427 } | 438 } |
| 428 | 439 |
| 429 | 440 |
| 430 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 441 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
| 431 Comment cmnt(masm_, "[ Assignment"); | 442 Comment cmnt(masm_, "[ Assignment"); |
| 432 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 443 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
| 433 | 444 |
| 434 // Left-hand side can only be a global or a (parameter or local) slot. | 445 // Left-hand side can only be a global or a (parameter or local) slot. |
| 435 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 446 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 436 ASSERT(var != NULL); | 447 ASSERT(var != NULL); |
| 437 ASSERT(var->is_global() || var->slot() != NULL); | 448 ASSERT(var->is_global() || var->slot() != NULL); |
| 438 | 449 |
| 439 Expression* rhs = expr->value(); | 450 Expression* rhs = expr->value(); |
| 440 if (var->is_global()) { | 451 if (var->is_global()) { |
| 441 // Assignment to a global variable, use inline caching. Right-hand-side | 452 // Assignment to a global variable, use inline caching. Right-hand-side |
| 442 // value is passed in eax, variable name in ecx, and the global object | 453 // value is passed in eax, variable name in ecx, and the global object |
| 443 // on the stack. | 454 // on the stack. |
| 444 | 455 |
| 445 // Code for the right-hand-side expression depends on its type. | 456 // Code for the right-hand-side expression depends on its type. |
| 446 if (rhs->AsLiteral() != NULL) { | 457 if (rhs->AsLiteral() != NULL) { |
| 447 __ mov(eax, rhs->AsLiteral()->handle()); | 458 __ mov(eax, rhs->AsLiteral()->handle()); |
| 448 } else { | 459 } else { |
| 449 ASSERT(rhs->location().is_temporary()); | 460 ASSERT(rhs->location().is_value()); |
| 450 Visit(rhs); | 461 Visit(rhs); |
| 451 __ pop(eax); | 462 __ pop(eax); |
| 452 } | 463 } |
| 453 __ mov(ecx, var->name()); | 464 __ mov(ecx, var->name()); |
| 454 __ push(CodeGenerator::GlobalObject()); | 465 __ push(CodeGenerator::GlobalObject()); |
| 455 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 466 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 456 __ call(ic, RelocInfo::CODE_TARGET); | 467 __ call(ic, RelocInfo::CODE_TARGET); |
| 457 // Overwrite the global object on the stack with the result if needed. | 468 // Overwrite the global object on the stack with the result if needed. |
| 458 DropAndMove(expr->location(), eax); | 469 DropAndMove(expr->location(), eax); |
| 459 } else { | 470 } else { |
| 460 // Local or parameter assignment. | 471 // Local or parameter assignment. |
| 461 | 472 |
| 462 // Code for the right-hand side expression depends on its type. | 473 // Code for the right-hand side expression depends on its type. |
| 463 if (rhs->AsLiteral() != NULL) { | 474 if (rhs->AsLiteral() != NULL) { |
| 464 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 475 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
| 465 // discarded result. Always perform the assignment. | 476 // discarded result. Always perform the assignment. |
| 466 __ mov(eax, rhs->AsLiteral()->handle()); | 477 __ mov(eax, rhs->AsLiteral()->handle()); |
| 467 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 478 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
| 468 Move(expr->location(), eax); | 479 Move(expr->location(), eax); |
| 469 } else { | 480 } else { |
| 470 ASSERT(rhs->location().is_temporary()); | 481 ASSERT(rhs->location().is_value()); |
| 471 Visit(rhs); | 482 Visit(rhs); |
| 472 switch (expr->location().type()) { | 483 switch (expr->location().type()) { |
| 473 case Location::NOWHERE: | 484 case Location::UNINITIALIZED: |
| 485 UNREACHABLE(); |
| 486 case Location::EFFECT: |
| 474 // Case 'var = temp'. Discard right-hand-side temporary. | 487 // Case 'var = temp'. Discard right-hand-side temporary. |
| 475 Move(var->slot(), rhs->location()); | 488 Move(var->slot(), rhs->location()); |
| 476 break; | 489 break; |
| 477 case Location::TEMP: | 490 case Location::VALUE: |
| 478 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 491 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side |
| 479 // temporary on the stack. | 492 // temporary on the stack. |
| 480 __ mov(eax, Operand(esp, 0)); | 493 __ mov(eax, Operand(esp, 0)); |
| 481 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 494 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
| 482 break; | 495 break; |
| 483 } | 496 } |
| 484 } | 497 } |
| 485 } | 498 } |
| 486 } | 499 } |
| 487 | 500 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 512 Visit(expr->key()); | 525 Visit(expr->key()); |
| 513 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 526 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 514 __ call(ic, RelocInfo::CODE_TARGET); | 527 __ call(ic, RelocInfo::CODE_TARGET); |
| 515 // By emitting a nop we make sure that we do not have a "test eax,..." | 528 // By emitting a nop we make sure that we do not have a "test eax,..." |
| 516 // instruction after the call it is treated specially by the LoadIC code. | 529 // instruction after the call it is treated specially by the LoadIC code. |
| 517 __ nop(); | 530 __ nop(); |
| 518 // Drop key left on the stack by IC. | 531 // Drop key left on the stack by IC. |
| 519 __ add(Operand(esp), Immediate(kPointerSize)); | 532 __ add(Operand(esp), Immediate(kPointerSize)); |
| 520 } | 533 } |
| 521 switch (expr->location().type()) { | 534 switch (expr->location().type()) { |
| 522 case Location::TEMP: | 535 case Location::UNINITIALIZED: |
| 536 UNREACHABLE(); |
| 537 case Location::VALUE: |
| 523 __ mov(Operand(esp, 0), eax); | 538 __ mov(Operand(esp, 0), eax); |
| 524 break; | 539 break; |
| 525 case Location::NOWHERE: | 540 case Location::EFFECT: |
| 526 __ add(Operand(esp), Immediate(kPointerSize)); | 541 __ add(Operand(esp), Immediate(kPointerSize)); |
| 527 break; | 542 break; |
| 528 } | 543 } |
| 529 } | 544 } |
| 530 | 545 |
| 531 | 546 |
| 532 void FastCodeGenerator::VisitCall(Call* expr) { | 547 void FastCodeGenerator::VisitCall(Call* expr) { |
| 533 Expression* fun = expr->expression(); | 548 Expression* fun = expr->expression(); |
| 534 ZoneList<Expression*>* args = expr->arguments(); | 549 ZoneList<Expression*>* args = expr->arguments(); |
| 535 Variable* var = fun->AsVariableProxy()->AsVariable(); | 550 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 536 ASSERT(var != NULL && !var->is_this() && var->is_global()); | 551 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
| 537 ASSERT(!var->is_possibly_eval()); | 552 ASSERT(!var->is_possibly_eval()); |
| 538 | 553 |
| 539 __ push(Immediate(var->name())); | 554 __ push(Immediate(var->name())); |
| 540 // Push global object (receiver). | 555 // Push global object (receiver). |
| 541 __ push(CodeGenerator::GlobalObject()); | 556 __ push(CodeGenerator::GlobalObject()); |
| 542 int arg_count = args->length(); | 557 int arg_count = args->length(); |
| 543 for (int i = 0; i < arg_count; i++) { | 558 for (int i = 0; i < arg_count; i++) { |
| 544 Visit(args->at(i)); | 559 Visit(args->at(i)); |
| 545 ASSERT(args->at(i)->location().is_temporary()); | 560 ASSERT(args->at(i)->location().is_value()); |
| 546 } | 561 } |
| 547 // Record source position for debugger | 562 // Record source position for debugger |
| 548 SetSourcePosition(expr->position()); | 563 SetSourcePosition(expr->position()); |
| 549 // Call the IC initialization code. | 564 // Call the IC initialization code. |
| 550 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 565 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 551 NOT_IN_LOOP); | 566 NOT_IN_LOOP); |
| 552 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 567 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 553 // Restore context register. | 568 // Restore context register. |
| 554 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 569 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 555 // Discard the function left on TOS. | 570 // Discard the function left on TOS. |
| 556 DropAndMove(expr->location(), eax); | 571 DropAndMove(expr->location(), eax); |
| 557 } | 572 } |
| 558 | 573 |
| 559 | 574 |
| 560 void FastCodeGenerator::VisitCallNew(CallNew* node) { | 575 void FastCodeGenerator::VisitCallNew(CallNew* node) { |
| 561 Comment cmnt(masm_, "[ CallNew"); | 576 Comment cmnt(masm_, "[ CallNew"); |
| 562 // According to ECMA-262, section 11.2.2, page 44, the function | 577 // According to ECMA-262, section 11.2.2, page 44, the function |
| 563 // expression in new calls must be evaluated before the | 578 // expression in new calls must be evaluated before the |
| 564 // arguments. | 579 // arguments. |
| 565 // Push function on the stack. | 580 // Push function on the stack. |
| 566 Visit(node->expression()); | 581 Visit(node->expression()); |
| 567 ASSERT(node->expression()->location().is_temporary()); | 582 ASSERT(node->expression()->location().is_value()); |
| 568 | 583 |
| 569 // Push global object (receiver). | 584 // Push global object (receiver). |
| 570 __ push(CodeGenerator::GlobalObject()); | 585 __ push(CodeGenerator::GlobalObject()); |
| 571 | 586 |
| 572 // Push the arguments ("left-to-right") on the stack. | 587 // Push the arguments ("left-to-right") on the stack. |
| 573 ZoneList<Expression*>* args = node->arguments(); | 588 ZoneList<Expression*>* args = node->arguments(); |
| 574 int arg_count = args->length(); | 589 int arg_count = args->length(); |
| 575 for (int i = 0; i < arg_count; i++) { | 590 for (int i = 0; i < arg_count; i++) { |
| 576 Visit(args->at(i)); | 591 Visit(args->at(i)); |
| 577 ASSERT(args->at(i)->location().is_temporary()); | 592 ASSERT(args->at(i)->location().is_value()); |
| 578 // If location is temporary, it is already on the stack, | 593 // If location is temporary, it is already on the stack, |
| 579 // so nothing to do here. | 594 // so nothing to do here. |
| 580 } | 595 } |
| 581 | 596 |
| 582 // Call the construct call builtin that handles allocation and | 597 // Call the construct call builtin that handles allocation and |
| 583 // constructor invocation. | 598 // constructor invocation. |
| 584 SetSourcePosition(node->position()); | 599 SetSourcePosition(node->position()); |
| 585 | 600 |
| 586 // Load function, arg_count into edi and eax. | 601 // Load function, arg_count into edi and eax. |
| 587 __ Set(eax, Immediate(arg_count)); | 602 __ Set(eax, Immediate(arg_count)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 600 Comment cmnt(masm_, "[ CallRuntime"); | 615 Comment cmnt(masm_, "[ CallRuntime"); |
| 601 ZoneList<Expression*>* args = expr->arguments(); | 616 ZoneList<Expression*>* args = expr->arguments(); |
| 602 Runtime::Function* function = expr->function(); | 617 Runtime::Function* function = expr->function(); |
| 603 | 618 |
| 604 ASSERT(function != NULL); | 619 ASSERT(function != NULL); |
| 605 | 620 |
| 606 // Push the arguments ("left-to-right"). | 621 // Push the arguments ("left-to-right"). |
| 607 int arg_count = args->length(); | 622 int arg_count = args->length(); |
| 608 for (int i = 0; i < arg_count; i++) { | 623 for (int i = 0; i < arg_count; i++) { |
| 609 Visit(args->at(i)); | 624 Visit(args->at(i)); |
| 610 ASSERT(args->at(i)->location().is_temporary()); | 625 ASSERT(args->at(i)->location().is_value()); |
| 611 } | 626 } |
| 612 | 627 |
| 613 __ CallRuntime(function, arg_count); | 628 __ CallRuntime(function, arg_count); |
| 614 Move(expr->location(), eax); | 629 Move(expr->location(), eax); |
| 615 } | 630 } |
| 616 | 631 |
| 617 | 632 |
| 618 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 633 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 619 // Compile a short-circuited boolean or operation in a non-test | 634 // Compile a short-circuited boolean or operation in a non-test |
| 620 // context. | 635 // context. |
| 621 ASSERT(expr->op() == Token::OR); | 636 ASSERT(expr->op() == Token::OR); |
| 622 // Compile (e0 || e1) as if it were | 637 // Compile (e0 || e1) as if it were |
| 623 // (let (temp = e0) temp ? temp : e1). | 638 // (let (temp = e0) temp ? temp : e1). |
| 624 | 639 |
| 625 Label eval_right, done; | 640 Label eval_right, done; |
| 626 Location destination = expr->location(); | 641 Location destination = expr->location(); |
| 627 Expression* left = expr->left(); | 642 Expression* left = expr->left(); |
| 628 Expression* right = expr->right(); | 643 Expression* right = expr->right(); |
| 629 | 644 |
| 630 // Use the shared ToBoolean stub to find the boolean value of the | 645 // Use the shared ToBoolean stub to find the boolean value of the |
| 631 // left-hand subexpression. Load the value into eax to perform some | 646 // left-hand subexpression. Load the value into eax to perform some |
| 632 // inlined checks assumed by the stub. | 647 // inlined checks assumed by the stub. |
| 633 | 648 |
| 634 // Compile the left-hand value into eax. Put it on the stack if we may | 649 // Compile the left-hand value into eax. Put it on the stack if we may |
| 635 // need it as the value of the whole expression. | 650 // need it as the value of the whole expression. |
| 636 if (left->AsLiteral() != NULL) { | 651 if (left->AsLiteral() != NULL) { |
| 637 __ mov(eax, left->AsLiteral()->handle()); | 652 __ mov(eax, left->AsLiteral()->handle()); |
| 638 if (destination.is_temporary()) __ push(eax); | 653 if (destination.is_value()) __ push(eax); |
| 639 } else { | 654 } else { |
| 640 Visit(left); | 655 Visit(left); |
| 641 ASSERT(left->location().is_temporary()); | 656 ASSERT(left->location().is_value()); |
| 642 switch (destination.type()) { | 657 switch (destination.type()) { |
| 643 case Location::NOWHERE: | 658 case Location::UNINITIALIZED: |
| 659 UNREACHABLE(); |
| 660 case Location::EFFECT: |
| 644 // Pop the left-hand value into eax because we will not need it as the | 661 // Pop the left-hand value into eax because we will not need it as the |
| 645 // final result. | 662 // final result. |
| 646 __ pop(eax); | 663 __ pop(eax); |
| 647 break; | 664 break; |
| 648 case Location::TEMP: | 665 case Location::VALUE: |
| 649 // Copy the left-hand value into eax because we may need it as the | 666 // Copy the left-hand value into eax because we may need it as the |
| 650 // final result. | 667 // final result. |
| 651 __ mov(eax, Operand(esp, 0)); | 668 __ mov(eax, Operand(esp, 0)); |
| 652 break; | 669 break; |
| 653 } | 670 } |
| 654 } | 671 } |
| 655 // The left-hand value is in eax. It is also on the stack iff the | 672 // The left-hand value is in eax. It is also on the stack iff the |
| 656 // destination location is temporary. | 673 // destination location is temporary. |
| 657 | 674 |
| 658 // Perform fast checks assumed by the stub. | 675 // Perform fast checks assumed by the stub. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 670 | 687 |
| 671 // Call the stub for all other cases. | 688 // Call the stub for all other cases. |
| 672 __ push(eax); | 689 __ push(eax); |
| 673 ToBooleanStub stub; | 690 ToBooleanStub stub; |
| 674 __ CallStub(&stub); | 691 __ CallStub(&stub); |
| 675 __ test(eax, Operand(eax)); // The stub returns nonzero for true. | 692 __ test(eax, Operand(eax)); // The stub returns nonzero for true. |
| 676 __ j(not_zero, &done); | 693 __ j(not_zero, &done); |
| 677 | 694 |
| 678 __ bind(&eval_right); | 695 __ bind(&eval_right); |
| 679 // Discard the left-hand value if present on the stack. | 696 // Discard the left-hand value if present on the stack. |
| 680 if (destination.is_temporary()) { | 697 if (destination.is_value()) { |
| 681 __ add(Operand(esp), Immediate(kPointerSize)); | 698 __ add(Operand(esp), Immediate(kPointerSize)); |
| 682 } | 699 } |
| 683 // Save or discard the right-hand value as needed. | 700 // Save or discard the right-hand value as needed. |
| 684 if (right->AsLiteral() != NULL) { | 701 if (right->AsLiteral() != NULL) { |
| 685 Move(destination, right->AsLiteral()); | 702 Move(destination, right->AsLiteral()); |
| 686 } else { | 703 } else { |
| 687 Visit(right); | 704 Visit(right); |
| 688 Move(destination, right->location()); | 705 Move(destination, right->location()); |
| 689 } | 706 } |
| 690 | 707 |
| 691 __ bind(&done); | 708 __ bind(&done); |
| 692 } | 709 } |
| 693 | 710 |
| 694 | 711 |
| 695 } } // namespace v8::internal | 712 } } // namespace v8::internal |
| OLD | NEW |