| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 // | 45 // |
| 46 // The live registers are: | 46 // The live registers are: |
| 47 // o r1: the JS function object being called (ie, ourselves) | 47 // o r1: the JS function object being called (ie, ourselves) |
| 48 // o cp: our context | 48 // o cp: our context |
| 49 // o fp: our caller's frame pointer | 49 // o fp: our caller's frame pointer |
| 50 // o sp: stack pointer | 50 // o sp: stack pointer |
| 51 // o lr: return address | 51 // o lr: return address |
| 52 // | 52 // |
| 53 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 53 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
| 54 // frames-arm.h for its layout. | 54 // frames-arm.h for its layout. |
| 55 void FastCodeGenerator::Generate(FunctionLiteral* fun) { | 55 void FullCodeGenerator::Generate(FunctionLiteral* fun) { |
| 56 function_ = fun; | 56 function_ = fun; |
| 57 SetFunctionPosition(fun); | 57 SetFunctionPosition(fun); |
| 58 int locals_count = fun->scope()->num_stack_slots(); | 58 int locals_count = fun->scope()->num_stack_slots(); |
| 59 | 59 |
| 60 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 60 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
| 61 if (locals_count > 0) { | 61 if (locals_count > 0) { |
| 62 // Load undefined value here, so the value is ready for the loop below. | 62 // Load undefined value here, so the value is ready for the loop below. |
| 63 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 63 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 64 } | 64 } |
| 65 // Adjust fp to point to caller's fp. | 65 // Adjust fp to point to caller's fp. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 | 160 |
| 161 { Comment cmnt(masm_, "[ return <undefined>;"); | 161 { Comment cmnt(masm_, "[ return <undefined>;"); |
| 162 // Emit a 'return undefined' in case control fell off the end of the | 162 // Emit a 'return undefined' in case control fell off the end of the |
| 163 // body. | 163 // body. |
| 164 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 164 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 165 } | 165 } |
| 166 EmitReturnSequence(function_->end_position()); | 166 EmitReturnSequence(function_->end_position()); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 void FastCodeGenerator::EmitReturnSequence(int position) { | 170 void FullCodeGenerator::EmitReturnSequence(int position) { |
| 171 Comment cmnt(masm_, "[ Return sequence"); | 171 Comment cmnt(masm_, "[ Return sequence"); |
| 172 if (return_label_.is_bound()) { | 172 if (return_label_.is_bound()) { |
| 173 __ b(&return_label_); | 173 __ b(&return_label_); |
| 174 } else { | 174 } else { |
| 175 __ bind(&return_label_); | 175 __ bind(&return_label_); |
| 176 if (FLAG_trace) { | 176 if (FLAG_trace) { |
| 177 // Push the return value on the stack as the parameter. | 177 // Push the return value on the stack as the parameter. |
| 178 // Runtime::TraceExit returns its parameter in r0. | 178 // Runtime::TraceExit returns its parameter in r0. |
| 179 __ push(r0); | 179 __ push(r0); |
| 180 __ CallRuntime(Runtime::kTraceExit, 1); | 180 __ CallRuntime(Runtime::kTraceExit, 1); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 207 // mode 1 instruction where there are restrictions on which immediate values | 207 // mode 1 instruction where there are restrictions on which immediate values |
| 208 // can be encoded in the instruction and which immediate values requires | 208 // can be encoded in the instruction and which immediate values requires |
| 209 // use of an additional instruction for moving the immediate to a temporary | 209 // use of an additional instruction for moving the immediate to a temporary |
| 210 // register. | 210 // register. |
| 211 ASSERT_EQ(return_sequence_length, | 211 ASSERT_EQ(return_sequence_length, |
| 212 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | 212 masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 | 215 |
| 216 | 216 |
| 217 void FastCodeGenerator::Apply(Expression::Context context, Register reg) { | 217 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { |
| 218 switch (context) { | 218 switch (context) { |
| 219 case Expression::kUninitialized: | 219 case Expression::kUninitialized: |
| 220 UNREACHABLE(); | 220 UNREACHABLE(); |
| 221 | 221 |
| 222 case Expression::kEffect: | 222 case Expression::kEffect: |
| 223 // Nothing to do. | 223 // Nothing to do. |
| 224 break; | 224 break; |
| 225 | 225 |
| 226 case Expression::kValue: | 226 case Expression::kValue: |
| 227 // Move value into place. | 227 // Move value into place. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 243 | 243 |
| 244 case Expression::kTest: | 244 case Expression::kTest: |
| 245 // We always call the runtime on ARM, so push the value as argument. | 245 // We always call the runtime on ARM, so push the value as argument. |
| 246 __ push(reg); | 246 __ push(reg); |
| 247 DoTest(context); | 247 DoTest(context); |
| 248 break; | 248 break; |
| 249 } | 249 } |
| 250 } | 250 } |
| 251 | 251 |
| 252 | 252 |
| 253 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 253 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
| 254 switch (context) { | 254 switch (context) { |
| 255 case Expression::kUninitialized: | 255 case Expression::kUninitialized: |
| 256 UNREACHABLE(); | 256 UNREACHABLE(); |
| 257 case Expression::kEffect: | 257 case Expression::kEffect: |
| 258 // Nothing to do. | 258 // Nothing to do. |
| 259 break; | 259 break; |
| 260 case Expression::kValue: | 260 case Expression::kValue: |
| 261 case Expression::kTest: | 261 case Expression::kTest: |
| 262 case Expression::kValueTest: | 262 case Expression::kValueTest: |
| 263 case Expression::kTestValue: | 263 case Expression::kTestValue: |
| 264 // On ARM we have to move the value into a register to do anything | 264 // On ARM we have to move the value into a register to do anything |
| 265 // with it. | 265 // with it. |
| 266 Move(result_register(), slot); | 266 Move(result_register(), slot); |
| 267 Apply(context, result_register()); | 267 Apply(context, result_register()); |
| 268 break; | 268 break; |
| 269 } | 269 } |
| 270 } | 270 } |
| 271 | 271 |
| 272 | 272 |
| 273 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 273 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
| 274 switch (context) { | 274 switch (context) { |
| 275 case Expression::kUninitialized: | 275 case Expression::kUninitialized: |
| 276 UNREACHABLE(); | 276 UNREACHABLE(); |
| 277 case Expression::kEffect: | 277 case Expression::kEffect: |
| 278 break; | 278 break; |
| 279 // Nothing to do. | 279 // Nothing to do. |
| 280 case Expression::kValue: | 280 case Expression::kValue: |
| 281 case Expression::kTest: | 281 case Expression::kTest: |
| 282 case Expression::kValueTest: | 282 case Expression::kValueTest: |
| 283 case Expression::kTestValue: | 283 case Expression::kTestValue: |
| 284 // On ARM we have to move the value into a register to do anything | 284 // On ARM we have to move the value into a register to do anything |
| 285 // with it. | 285 // with it. |
| 286 __ mov(result_register(), Operand(lit->handle())); | 286 __ mov(result_register(), Operand(lit->handle())); |
| 287 Apply(context, result_register()); | 287 Apply(context, result_register()); |
| 288 break; | 288 break; |
| 289 } | 289 } |
| 290 } | 290 } |
| 291 | 291 |
| 292 | 292 |
| 293 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | 293 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
| 294 switch (context) { | 294 switch (context) { |
| 295 case Expression::kUninitialized: | 295 case Expression::kUninitialized: |
| 296 UNREACHABLE(); | 296 UNREACHABLE(); |
| 297 | 297 |
| 298 case Expression::kEffect: | 298 case Expression::kEffect: |
| 299 __ Drop(1); | 299 __ Drop(1); |
| 300 break; | 300 break; |
| 301 | 301 |
| 302 case Expression::kValue: | 302 case Expression::kValue: |
| 303 switch (location_) { | 303 switch (location_) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 316 __ push(ip); | 316 __ push(ip); |
| 317 // Fall through. | 317 // Fall through. |
| 318 | 318 |
| 319 case Expression::kTest: | 319 case Expression::kTest: |
| 320 DoTest(context); | 320 DoTest(context); |
| 321 break; | 321 break; |
| 322 } | 322 } |
| 323 } | 323 } |
| 324 | 324 |
| 325 | 325 |
| 326 void FastCodeGenerator::DropAndApply(int count, | 326 void FullCodeGenerator::DropAndApply(int count, |
| 327 Expression::Context context, | 327 Expression::Context context, |
| 328 Register reg) { | 328 Register reg) { |
| 329 ASSERT(count > 0); | 329 ASSERT(count > 0); |
| 330 ASSERT(!reg.is(sp)); | 330 ASSERT(!reg.is(sp)); |
| 331 switch (context) { | 331 switch (context) { |
| 332 case Expression::kUninitialized: | 332 case Expression::kUninitialized: |
| 333 UNREACHABLE(); | 333 UNREACHABLE(); |
| 334 | 334 |
| 335 case Expression::kEffect: | 335 case Expression::kEffect: |
| 336 __ Drop(count); | 336 __ Drop(count); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 364 __ Drop(count - 2); | 364 __ Drop(count - 2); |
| 365 __ str(reg, MemOperand(sp, kPointerSize)); | 365 __ str(reg, MemOperand(sp, kPointerSize)); |
| 366 __ str(reg, MemOperand(sp)); | 366 __ str(reg, MemOperand(sp)); |
| 367 } | 367 } |
| 368 DoTest(context); | 368 DoTest(context); |
| 369 break; | 369 break; |
| 370 } | 370 } |
| 371 } | 371 } |
| 372 | 372 |
| 373 | 373 |
| 374 void FastCodeGenerator::Apply(Expression::Context context, | 374 void FullCodeGenerator::Apply(Expression::Context context, |
| 375 Label* materialize_true, | 375 Label* materialize_true, |
| 376 Label* materialize_false) { | 376 Label* materialize_false) { |
| 377 switch (context) { | 377 switch (context) { |
| 378 case Expression::kUninitialized: | 378 case Expression::kUninitialized: |
| 379 | 379 |
| 380 case Expression::kEffect: | 380 case Expression::kEffect: |
| 381 ASSERT_EQ(materialize_true, materialize_false); | 381 ASSERT_EQ(materialize_true, materialize_false); |
| 382 __ bind(materialize_true); | 382 __ bind(materialize_true); |
| 383 break; | 383 break; |
| 384 | 384 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 case kStack: | 425 case kStack: |
| 426 __ push(result_register()); | 426 __ push(result_register()); |
| 427 break; | 427 break; |
| 428 } | 428 } |
| 429 __ jmp(false_label_); | 429 __ jmp(false_label_); |
| 430 break; | 430 break; |
| 431 } | 431 } |
| 432 } | 432 } |
| 433 | 433 |
| 434 | 434 |
| 435 void FastCodeGenerator::DoTest(Expression::Context context) { | 435 void FullCodeGenerator::DoTest(Expression::Context context) { |
| 436 // The value to test is pushed on the stack, and duplicated on the stack | 436 // The value to test is pushed on the stack, and duplicated on the stack |
| 437 // if necessary (for value/test and test/value contexts). | 437 // if necessary (for value/test and test/value contexts). |
| 438 ASSERT_NE(NULL, true_label_); | 438 ASSERT_NE(NULL, true_label_); |
| 439 ASSERT_NE(NULL, false_label_); | 439 ASSERT_NE(NULL, false_label_); |
| 440 | 440 |
| 441 // Call the runtime to find the boolean value of the source and then | 441 // Call the runtime to find the boolean value of the source and then |
| 442 // translate it into control flow to the pair of labels. | 442 // translate it into control flow to the pair of labels. |
| 443 __ CallRuntime(Runtime::kToBool, 1); | 443 __ CallRuntime(Runtime::kToBool, 1); |
| 444 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 444 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 445 __ cmp(r0, ip); | 445 __ cmp(r0, ip); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 } | 488 } |
| 489 __ bind(&discard); | 489 __ bind(&discard); |
| 490 __ Drop(1); | 490 __ Drop(1); |
| 491 __ jmp(true_label_); | 491 __ jmp(true_label_); |
| 492 break; | 492 break; |
| 493 } | 493 } |
| 494 } | 494 } |
| 495 } | 495 } |
| 496 | 496 |
| 497 | 497 |
| 498 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 498 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 499 switch (slot->type()) { | 499 switch (slot->type()) { |
| 500 case Slot::PARAMETER: | 500 case Slot::PARAMETER: |
| 501 case Slot::LOCAL: | 501 case Slot::LOCAL: |
| 502 return MemOperand(fp, SlotOffset(slot)); | 502 return MemOperand(fp, SlotOffset(slot)); |
| 503 case Slot::CONTEXT: { | 503 case Slot::CONTEXT: { |
| 504 int context_chain_length = | 504 int context_chain_length = |
| 505 function_->scope()->ContextChainLength(slot->var()->scope()); | 505 function_->scope()->ContextChainLength(slot->var()->scope()); |
| 506 __ LoadContext(scratch, context_chain_length); | 506 __ LoadContext(scratch, context_chain_length); |
| 507 return CodeGenerator::ContextOperand(scratch, slot->index()); | 507 return CodeGenerator::ContextOperand(scratch, slot->index()); |
| 508 } | 508 } |
| 509 case Slot::LOOKUP: | 509 case Slot::LOOKUP: |
| 510 UNREACHABLE(); | 510 UNREACHABLE(); |
| 511 } | 511 } |
| 512 UNREACHABLE(); | 512 UNREACHABLE(); |
| 513 return MemOperand(r0, 0); | 513 return MemOperand(r0, 0); |
| 514 } | 514 } |
| 515 | 515 |
| 516 | 516 |
| 517 void FastCodeGenerator::Move(Register destination, Slot* source) { | 517 void FullCodeGenerator::Move(Register destination, Slot* source) { |
| 518 // Use destination as scratch. | 518 // Use destination as scratch. |
| 519 MemOperand slot_operand = EmitSlotSearch(source, destination); | 519 MemOperand slot_operand = EmitSlotSearch(source, destination); |
| 520 __ ldr(destination, slot_operand); | 520 __ ldr(destination, slot_operand); |
| 521 } | 521 } |
| 522 | 522 |
| 523 | 523 |
| 524 void FastCodeGenerator::Move(Slot* dst, | 524 void FullCodeGenerator::Move(Slot* dst, |
| 525 Register src, | 525 Register src, |
| 526 Register scratch1, | 526 Register scratch1, |
| 527 Register scratch2) { | 527 Register scratch2) { |
| 528 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 528 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 529 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 529 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 530 MemOperand location = EmitSlotSearch(dst, scratch1); | 530 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 531 __ str(src, location); | 531 __ str(src, location); |
| 532 // Emit the write barrier code if the location is in the heap. | 532 // Emit the write barrier code if the location is in the heap. |
| 533 if (dst->type() == Slot::CONTEXT) { | 533 if (dst->type() == Slot::CONTEXT) { |
| 534 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); | 534 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); |
| 535 __ RecordWrite(scratch1, scratch2, src); | 535 __ RecordWrite(scratch1, scratch2, src); |
| 536 } | 536 } |
| 537 } | 537 } |
| 538 | 538 |
| 539 | 539 |
| 540 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 540 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
| 541 Comment cmnt(masm_, "[ Declaration"); | 541 Comment cmnt(masm_, "[ Declaration"); |
| 542 Variable* var = decl->proxy()->var(); | 542 Variable* var = decl->proxy()->var(); |
| 543 ASSERT(var != NULL); // Must have been resolved. | 543 ASSERT(var != NULL); // Must have been resolved. |
| 544 Slot* slot = var->slot(); | 544 Slot* slot = var->slot(); |
| 545 Property* prop = var->AsProperty(); | 545 Property* prop = var->AsProperty(); |
| 546 | 546 |
| 547 if (slot != NULL) { | 547 if (slot != NULL) { |
| 548 switch (slot->type()) { | 548 switch (slot->type()) { |
| 549 case Slot::PARAMETER: | 549 case Slot::PARAMETER: |
| 550 case Slot::LOCAL: | 550 case Slot::LOCAL: |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 __ Call(ic, RelocInfo::CODE_TARGET); | 630 __ Call(ic, RelocInfo::CODE_TARGET); |
| 631 | 631 |
| 632 // Value in r0 is ignored (declarations are statements). Receiver | 632 // Value in r0 is ignored (declarations are statements). Receiver |
| 633 // and key on stack are discarded. | 633 // and key on stack are discarded. |
| 634 __ Drop(2); | 634 __ Drop(2); |
| 635 } | 635 } |
| 636 } | 636 } |
| 637 } | 637 } |
| 638 | 638 |
| 639 | 639 |
| 640 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 640 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 641 // Call the runtime to declare the globals. | 641 // Call the runtime to declare the globals. |
| 642 // The context is the first argument. | 642 // The context is the first argument. |
| 643 __ mov(r1, Operand(pairs)); | 643 __ mov(r1, Operand(pairs)); |
| 644 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); | 644 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); |
| 645 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); | 645 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); |
| 646 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 646 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 647 // Return value is ignored. | 647 // Return value is ignored. |
| 648 } | 648 } |
| 649 | 649 |
| 650 | 650 |
| 651 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 651 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 652 Comment cmnt(masm_, "[ FunctionLiteral"); | 652 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 653 | 653 |
| 654 // Build the function boilerplate and instantiate it. | 654 // Build the function boilerplate and instantiate it. |
| 655 Handle<JSFunction> boilerplate = | 655 Handle<JSFunction> boilerplate = |
| 656 Compiler::BuildBoilerplate(expr, script_, this); | 656 Compiler::BuildBoilerplate(expr, script_, this); |
| 657 if (HasStackOverflow()) return; | 657 if (HasStackOverflow()) return; |
| 658 | 658 |
| 659 ASSERT(boilerplate->IsBoilerplate()); | 659 ASSERT(boilerplate->IsBoilerplate()); |
| 660 | 660 |
| 661 // Create a new closure. | 661 // Create a new closure. |
| 662 __ mov(r0, Operand(boilerplate)); | 662 __ mov(r0, Operand(boilerplate)); |
| 663 __ stm(db_w, sp, cp.bit() | r0.bit()); | 663 __ stm(db_w, sp, cp.bit() | r0.bit()); |
| 664 __ CallRuntime(Runtime::kNewClosure, 2); | 664 __ CallRuntime(Runtime::kNewClosure, 2); |
| 665 Apply(context_, r0); | 665 Apply(context_, r0); |
| 666 } | 666 } |
| 667 | 667 |
| 668 | 668 |
| 669 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 669 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 670 Comment cmnt(masm_, "[ VariableProxy"); | 670 Comment cmnt(masm_, "[ VariableProxy"); |
| 671 EmitVariableLoad(expr->var(), context_); | 671 EmitVariableLoad(expr->var(), context_); |
| 672 } | 672 } |
| 673 | 673 |
| 674 | 674 |
| 675 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 675 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
| 676 Expression::Context context) { | 676 Expression::Context context) { |
| 677 Expression* rewrite = var->rewrite(); | 677 Expression* rewrite = var->rewrite(); |
| 678 if (rewrite == NULL) { | 678 if (rewrite == NULL) { |
| 679 ASSERT(var->is_global()); | 679 ASSERT(var->is_global()); |
| 680 Comment cmnt(masm_, "Global variable"); | 680 Comment cmnt(masm_, "Global variable"); |
| 681 // Use inline caching. Variable name is passed in r2 and the global | 681 // Use inline caching. Variable name is passed in r2 and the global |
| 682 // object on the stack. | 682 // object on the stack. |
| 683 __ ldr(ip, CodeGenerator::GlobalObject()); | 683 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 684 __ push(ip); | 684 __ push(ip); |
| 685 __ mov(r2, Operand(var->name())); | 685 __ mov(r2, Operand(var->name())); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 // Do a keyed property load. | 738 // Do a keyed property load. |
| 739 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 739 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 740 __ Call(ic, RelocInfo::CODE_TARGET); | 740 __ Call(ic, RelocInfo::CODE_TARGET); |
| 741 | 741 |
| 742 // Drop key and object left on the stack by IC, and push the result. | 742 // Drop key and object left on the stack by IC, and push the result. |
| 743 DropAndApply(2, context, r0); | 743 DropAndApply(2, context, r0); |
| 744 } | 744 } |
| 745 } | 745 } |
| 746 | 746 |
| 747 | 747 |
| 748 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 748 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 749 Comment cmnt(masm_, "[ RegExpLiteral"); | 749 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 750 Label done; | 750 Label done; |
| 751 // Registers will be used as follows: | 751 // Registers will be used as follows: |
| 752 // r4 = JS function, literals array | 752 // r4 = JS function, literals array |
| 753 // r3 = literal index | 753 // r3 = literal index |
| 754 // r2 = RegExp pattern | 754 // r2 = RegExp pattern |
| 755 // r1 = RegExp flags | 755 // r1 = RegExp flags |
| 756 // r0 = temp + return value (RegExp literal) | 756 // r0 = temp + return value (RegExp literal) |
| 757 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 757 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 758 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 758 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
| 759 int literal_offset = | 759 int literal_offset = |
| 760 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 760 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 761 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 761 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
| 762 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 762 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 763 __ cmp(r0, ip); | 763 __ cmp(r0, ip); |
| 764 __ b(ne, &done); | 764 __ b(ne, &done); |
| 765 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 765 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
| 766 __ mov(r2, Operand(expr->pattern())); | 766 __ mov(r2, Operand(expr->pattern())); |
| 767 __ mov(r1, Operand(expr->flags())); | 767 __ mov(r1, Operand(expr->flags())); |
| 768 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | 768 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
| 769 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 769 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 770 __ bind(&done); | 770 __ bind(&done); |
| 771 Apply(context_, r0); | 771 Apply(context_, r0); |
| 772 } | 772 } |
| 773 | 773 |
| 774 | 774 |
| 775 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 775 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 776 Comment cmnt(masm_, "[ ObjectLiteral"); | 776 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 777 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 777 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 778 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 778 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
| 779 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); | 779 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); |
| 780 __ mov(r0, Operand(expr->constant_properties())); | 780 __ mov(r0, Operand(expr->constant_properties())); |
| 781 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); | 781 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); |
| 782 if (expr->depth() > 1) { | 782 if (expr->depth() > 1) { |
| 783 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); | 783 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); |
| 784 } else { | 784 } else { |
| 785 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); | 785 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 } | 840 } |
| 841 | 841 |
| 842 if (result_saved) { | 842 if (result_saved) { |
| 843 ApplyTOS(context_); | 843 ApplyTOS(context_); |
| 844 } else { | 844 } else { |
| 845 Apply(context_, r0); | 845 Apply(context_, r0); |
| 846 } | 846 } |
| 847 } | 847 } |
| 848 | 848 |
| 849 | 849 |
| 850 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 850 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 851 Comment cmnt(masm_, "[ ArrayLiteral"); | 851 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 852 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 852 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 853 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 853 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
| 854 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 854 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
| 855 __ mov(r1, Operand(expr->constant_elements())); | 855 __ mov(r1, Operand(expr->constant_elements())); |
| 856 __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); | 856 __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); |
| 857 if (expr->depth() > 1) { | 857 if (expr->depth() > 1) { |
| 858 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 858 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
| 859 } else { | 859 } else { |
| 860 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 860 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 } | 893 } |
| 894 | 894 |
| 895 if (result_saved) { | 895 if (result_saved) { |
| 896 ApplyTOS(context_); | 896 ApplyTOS(context_); |
| 897 } else { | 897 } else { |
| 898 Apply(context_, r0); | 898 Apply(context_, r0); |
| 899 } | 899 } |
| 900 } | 900 } |
| 901 | 901 |
| 902 | 902 |
| 903 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 903 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 904 SetSourcePosition(prop->position()); | 904 SetSourcePosition(prop->position()); |
| 905 Literal* key = prop->key()->AsLiteral(); | 905 Literal* key = prop->key()->AsLiteral(); |
| 906 __ mov(r2, Operand(key->handle())); | 906 __ mov(r2, Operand(key->handle())); |
| 907 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 907 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 908 __ Call(ic, RelocInfo::CODE_TARGET); | 908 __ Call(ic, RelocInfo::CODE_TARGET); |
| 909 } | 909 } |
| 910 | 910 |
| 911 | 911 |
| 912 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 912 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 913 SetSourcePosition(prop->position()); | 913 SetSourcePosition(prop->position()); |
| 914 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 914 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 915 __ Call(ic, RelocInfo::CODE_TARGET); | 915 __ Call(ic, RelocInfo::CODE_TARGET); |
| 916 } | 916 } |
| 917 | 917 |
| 918 | 918 |
| 919 void FastCodeGenerator::EmitBinaryOp(Token::Value op, | 919 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
| 920 Expression::Context context) { | 920 Expression::Context context) { |
| 921 __ pop(r1); | 921 __ pop(r1); |
| 922 GenericBinaryOpStub stub(op, NO_OVERWRITE); | 922 GenericBinaryOpStub stub(op, NO_OVERWRITE); |
| 923 __ CallStub(&stub); | 923 __ CallStub(&stub); |
| 924 Apply(context, r0); | 924 Apply(context, r0); |
| 925 } | 925 } |
| 926 | 926 |
| 927 | 927 |
| 928 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 928 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 929 Expression::Context context) { | 929 Expression::Context context) { |
| 930 ASSERT(var != NULL); | 930 ASSERT(var != NULL); |
| 931 ASSERT(var->is_global() || var->slot() != NULL); | 931 ASSERT(var->is_global() || var->slot() != NULL); |
| 932 if (var->is_global()) { | 932 if (var->is_global()) { |
| 933 // Assignment to a global variable. Use inline caching for the | 933 // Assignment to a global variable. Use inline caching for the |
| 934 // assignment. Right-hand-side value is passed in r0, variable name in | 934 // assignment. Right-hand-side value is passed in r0, variable name in |
| 935 // r2, and the global object on the stack. | 935 // r2, and the global object on the stack. |
| 936 __ mov(r2, Operand(var->name())); | 936 __ mov(r2, Operand(var->name())); |
| 937 __ ldr(ip, CodeGenerator::GlobalObject()); | 937 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 938 __ push(ip); | 938 __ push(ip); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 968 } | 968 } |
| 969 Apply(context, result_register()); | 969 Apply(context, result_register()); |
| 970 } else { | 970 } else { |
| 971 // Variables rewritten as properties are not treated as variables in | 971 // Variables rewritten as properties are not treated as variables in |
| 972 // assignments. | 972 // assignments. |
| 973 UNREACHABLE(); | 973 UNREACHABLE(); |
| 974 } | 974 } |
| 975 } | 975 } |
| 976 | 976 |
| 977 | 977 |
| 978 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 978 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 979 // Assignment to a property, using a named store IC. | 979 // Assignment to a property, using a named store IC. |
| 980 Property* prop = expr->target()->AsProperty(); | 980 Property* prop = expr->target()->AsProperty(); |
| 981 ASSERT(prop != NULL); | 981 ASSERT(prop != NULL); |
| 982 ASSERT(prop->key()->AsLiteral() != NULL); | 982 ASSERT(prop->key()->AsLiteral() != NULL); |
| 983 | 983 |
| 984 // If the assignment starts a block of assignments to the same object, | 984 // If the assignment starts a block of assignments to the same object, |
| 985 // change to slow case to avoid the quadratic behavior of repeatedly | 985 // change to slow case to avoid the quadratic behavior of repeatedly |
| 986 // adding fast properties. | 986 // adding fast properties. |
| 987 if (expr->starts_initialization_block()) { | 987 if (expr->starts_initialization_block()) { |
| 988 __ push(result_register()); | 988 __ push(result_register()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1004 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. | 1004 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. |
| 1005 __ push(ip); | 1005 __ push(ip); |
| 1006 __ CallRuntime(Runtime::kToFastProperties, 1); | 1006 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1007 __ pop(r0); | 1007 __ pop(r0); |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 DropAndApply(1, context_, r0); | 1010 DropAndApply(1, context_, r0); |
| 1011 } | 1011 } |
| 1012 | 1012 |
| 1013 | 1013 |
| 1014 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1014 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1015 // Assignment to a property, using a keyed store IC. | 1015 // Assignment to a property, using a keyed store IC. |
| 1016 | 1016 |
| 1017 // If the assignment starts a block of assignments to the same object, | 1017 // If the assignment starts a block of assignments to the same object, |
| 1018 // change to slow case to avoid the quadratic behavior of repeatedly | 1018 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1019 // adding fast properties. | 1019 // adding fast properties. |
| 1020 if (expr->starts_initialization_block()) { | 1020 if (expr->starts_initialization_block()) { |
| 1021 __ push(result_register()); | 1021 __ push(result_register()); |
| 1022 // Receiver is now under the key and value. | 1022 // Receiver is now under the key and value. |
| 1023 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1023 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); |
| 1024 __ push(ip); | 1024 __ push(ip); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1039 __ push(ip); | 1039 __ push(ip); |
| 1040 __ CallRuntime(Runtime::kToFastProperties, 1); | 1040 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1041 __ pop(r0); | 1041 __ pop(r0); |
| 1042 } | 1042 } |
| 1043 | 1043 |
| 1044 // Receiver and key are still on stack. | 1044 // Receiver and key are still on stack. |
| 1045 DropAndApply(2, context_, r0); | 1045 DropAndApply(2, context_, r0); |
| 1046 } | 1046 } |
| 1047 | 1047 |
| 1048 | 1048 |
| 1049 void FastCodeGenerator::VisitProperty(Property* expr) { | 1049 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 1050 Comment cmnt(masm_, "[ Property"); | 1050 Comment cmnt(masm_, "[ Property"); |
| 1051 Expression* key = expr->key(); | 1051 Expression* key = expr->key(); |
| 1052 | 1052 |
| 1053 // Evaluate receiver. | 1053 // Evaluate receiver. |
| 1054 VisitForValue(expr->obj(), kStack); | 1054 VisitForValue(expr->obj(), kStack); |
| 1055 | 1055 |
| 1056 if (key->IsPropertyName()) { | 1056 if (key->IsPropertyName()) { |
| 1057 EmitNamedPropertyLoad(expr); | 1057 EmitNamedPropertyLoad(expr); |
| 1058 // Drop receiver left on the stack by IC. | 1058 // Drop receiver left on the stack by IC. |
| 1059 DropAndApply(1, context_, r0); | 1059 DropAndApply(1, context_, r0); |
| 1060 } else { | 1060 } else { |
| 1061 VisitForValue(expr->key(), kStack); | 1061 VisitForValue(expr->key(), kStack); |
| 1062 EmitKeyedPropertyLoad(expr); | 1062 EmitKeyedPropertyLoad(expr); |
| 1063 // Drop key and receiver left on the stack by IC. | 1063 // Drop key and receiver left on the stack by IC. |
| 1064 DropAndApply(2, context_, r0); | 1064 DropAndApply(2, context_, r0); |
| 1065 } | 1065 } |
| 1066 } | 1066 } |
| 1067 | 1067 |
| 1068 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1068 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 1069 Handle<Object> ignored, | 1069 Handle<Object> ignored, |
| 1070 RelocInfo::Mode mode) { | 1070 RelocInfo::Mode mode) { |
| 1071 // Code common for calls using the IC. | 1071 // Code common for calls using the IC. |
| 1072 ZoneList<Expression*>* args = expr->arguments(); | 1072 ZoneList<Expression*>* args = expr->arguments(); |
| 1073 int arg_count = args->length(); | 1073 int arg_count = args->length(); |
| 1074 for (int i = 0; i < arg_count; i++) { | 1074 for (int i = 0; i < arg_count; i++) { |
| 1075 VisitForValue(args->at(i), kStack); | 1075 VisitForValue(args->at(i), kStack); |
| 1076 } | 1076 } |
| 1077 // Record source position for debugger. | 1077 // Record source position for debugger. |
| 1078 SetSourcePosition(expr->position()); | 1078 SetSourcePosition(expr->position()); |
| 1079 // Call the IC initialization code. | 1079 // Call the IC initialization code. |
| 1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 1081 NOT_IN_LOOP); | 1081 NOT_IN_LOOP); |
| 1082 __ Call(ic, mode); | 1082 __ Call(ic, mode); |
| 1083 // Restore context register. | 1083 // Restore context register. |
| 1084 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1084 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1085 // Discard the function left on TOS. | 1085 // Discard the function left on TOS. |
| 1086 DropAndApply(1, context_, r0); | 1086 DropAndApply(1, context_, r0); |
| 1087 } | 1087 } |
| 1088 | 1088 |
| 1089 | 1089 |
| 1090 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1090 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 1091 // Code common for calls using the call stub. | 1091 // Code common for calls using the call stub. |
| 1092 ZoneList<Expression*>* args = expr->arguments(); | 1092 ZoneList<Expression*>* args = expr->arguments(); |
| 1093 int arg_count = args->length(); | 1093 int arg_count = args->length(); |
| 1094 for (int i = 0; i < arg_count; i++) { | 1094 for (int i = 0; i < arg_count; i++) { |
| 1095 VisitForValue(args->at(i), kStack); | 1095 VisitForValue(args->at(i), kStack); |
| 1096 } | 1096 } |
| 1097 // Record source position for debugger. | 1097 // Record source position for debugger. |
| 1098 SetSourcePosition(expr->position()); | 1098 SetSourcePosition(expr->position()); |
| 1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
| 1100 __ CallStub(&stub); | 1100 __ CallStub(&stub); |
| 1101 // Restore context register. | 1101 // Restore context register. |
| 1102 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1102 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1103 // Discard the function left on TOS. | 1103 // Discard the function left on TOS. |
| 1104 DropAndApply(1, context_, r0); | 1104 DropAndApply(1, context_, r0); |
| 1105 } | 1105 } |
| 1106 | 1106 |
| 1107 | 1107 |
| 1108 void FastCodeGenerator::VisitCall(Call* expr) { | 1108 void FullCodeGenerator::VisitCall(Call* expr) { |
| 1109 Comment cmnt(masm_, "[ Call"); | 1109 Comment cmnt(masm_, "[ Call"); |
| 1110 Expression* fun = expr->expression(); | 1110 Expression* fun = expr->expression(); |
| 1111 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1111 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 1112 | 1112 |
| 1113 if (var != NULL && var->is_possibly_eval()) { | 1113 if (var != NULL && var->is_possibly_eval()) { |
| 1114 // Call to the identifier 'eval'. | 1114 // Call to the identifier 'eval'. |
| 1115 UNREACHABLE(); | 1115 UNREACHABLE(); |
| 1116 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1116 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 1117 // Call to a global variable. | 1117 // Call to a global variable. |
| 1118 __ mov(r1, Operand(var->name())); | 1118 __ mov(r1, Operand(var->name())); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1169 // Load global receiver object. | 1169 // Load global receiver object. |
| 1170 __ ldr(r1, CodeGenerator::GlobalObject()); | 1170 __ ldr(r1, CodeGenerator::GlobalObject()); |
| 1171 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 1171 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 1172 __ push(r1); | 1172 __ push(r1); |
| 1173 // Emit function call. | 1173 // Emit function call. |
| 1174 EmitCallWithStub(expr); | 1174 EmitCallWithStub(expr); |
| 1175 } | 1175 } |
| 1176 } | 1176 } |
| 1177 | 1177 |
| 1178 | 1178 |
| 1179 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 1179 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 1180 Comment cmnt(masm_, "[ CallNew"); | 1180 Comment cmnt(masm_, "[ CallNew"); |
| 1181 // According to ECMA-262, section 11.2.2, page 44, the function | 1181 // According to ECMA-262, section 11.2.2, page 44, the function |
| 1182 // expression in new calls must be evaluated before the | 1182 // expression in new calls must be evaluated before the |
| 1183 // arguments. | 1183 // arguments. |
| 1184 // Push function on the stack. | 1184 // Push function on the stack. |
| 1185 VisitForValue(expr->expression(), kStack); | 1185 VisitForValue(expr->expression(), kStack); |
| 1186 | 1186 |
| 1187 // Push global object (receiver). | 1187 // Push global object (receiver). |
| 1188 __ ldr(r0, CodeGenerator::GlobalObject()); | 1188 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 1189 __ push(r0); | 1189 __ push(r0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1204 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1204 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 1205 | 1205 |
| 1206 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1206 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
| 1207 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1207 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 1208 | 1208 |
| 1209 // Replace function on TOS with result in r0, or pop it. | 1209 // Replace function on TOS with result in r0, or pop it. |
| 1210 DropAndApply(1, context_, r0); | 1210 DropAndApply(1, context_, r0); |
| 1211 } | 1211 } |
| 1212 | 1212 |
| 1213 | 1213 |
| 1214 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1214 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1215 Comment cmnt(masm_, "[ CallRuntime"); | 1215 Comment cmnt(masm_, "[ CallRuntime"); |
| 1216 ZoneList<Expression*>* args = expr->arguments(); | 1216 ZoneList<Expression*>* args = expr->arguments(); |
| 1217 | 1217 |
| 1218 if (expr->is_jsruntime()) { | 1218 if (expr->is_jsruntime()) { |
| 1219 // Prepare for calling JS runtime function. | 1219 // Prepare for calling JS runtime function. |
| 1220 __ mov(r1, Operand(expr->name())); | 1220 __ mov(r1, Operand(expr->name())); |
| 1221 __ ldr(r0, CodeGenerator::GlobalObject()); | 1221 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 1222 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); | 1222 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); |
| 1223 __ stm(db_w, sp, r1.bit() | r0.bit()); | 1223 __ stm(db_w, sp, r1.bit() | r0.bit()); |
| 1224 } | 1224 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1239 // Discard the function left on TOS. | 1239 // Discard the function left on TOS. |
| 1240 DropAndApply(1, context_, r0); | 1240 DropAndApply(1, context_, r0); |
| 1241 } else { | 1241 } else { |
| 1242 // Call the C runtime function. | 1242 // Call the C runtime function. |
| 1243 __ CallRuntime(expr->function(), arg_count); | 1243 __ CallRuntime(expr->function(), arg_count); |
| 1244 Apply(context_, r0); | 1244 Apply(context_, r0); |
| 1245 } | 1245 } |
| 1246 } | 1246 } |
| 1247 | 1247 |
| 1248 | 1248 |
| 1249 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1249 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1250 switch (expr->op()) { | 1250 switch (expr->op()) { |
| 1251 case Token::VOID: { | 1251 case Token::VOID: { |
| 1252 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1252 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 1253 VisitForEffect(expr->expression()); | 1253 VisitForEffect(expr->expression()); |
| 1254 switch (context_) { | 1254 switch (context_) { |
| 1255 case Expression::kUninitialized: | 1255 case Expression::kUninitialized: |
| 1256 UNREACHABLE(); | 1256 UNREACHABLE(); |
| 1257 break; | 1257 break; |
| 1258 case Expression::kEffect: | 1258 case Expression::kEffect: |
| 1259 break; | 1259 break; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 Apply(context_, r0); | 1350 Apply(context_, r0); |
| 1351 break; | 1351 break; |
| 1352 } | 1352 } |
| 1353 | 1353 |
| 1354 default: | 1354 default: |
| 1355 UNREACHABLE(); | 1355 UNREACHABLE(); |
| 1356 } | 1356 } |
| 1357 } | 1357 } |
| 1358 | 1358 |
| 1359 | 1359 |
| 1360 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1360 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 1361 Comment cmnt(masm_, "[ CountOperation"); | 1361 Comment cmnt(masm_, "[ CountOperation"); |
| 1362 | 1362 |
| 1363 // Expression can only be a property, a global or a (parameter or local) | 1363 // Expression can only be a property, a global or a (parameter or local) |
| 1364 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1364 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 1365 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1365 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1366 LhsKind assign_type = VARIABLE; | 1366 LhsKind assign_type = VARIABLE; |
| 1367 Property* prop = expr->expression()->AsProperty(); | 1367 Property* prop = expr->expression()->AsProperty(); |
| 1368 // In case of a property we use the uninitialized expression context | 1368 // In case of a property we use the uninitialized expression context |
| 1369 // of the key to detect a named property. | 1369 // of the key to detect a named property. |
| 1370 if (prop != NULL) { | 1370 if (prop != NULL) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1476 } | 1476 } |
| 1477 } else { | 1477 } else { |
| 1478 DropAndApply(2, context_, r0); | 1478 DropAndApply(2, context_, r0); |
| 1479 } | 1479 } |
| 1480 break; | 1480 break; |
| 1481 } | 1481 } |
| 1482 } | 1482 } |
| 1483 } | 1483 } |
| 1484 | 1484 |
| 1485 | 1485 |
| 1486 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1486 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 1487 Comment cmnt(masm_, "[ BinaryOperation"); | 1487 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1488 switch (expr->op()) { | 1488 switch (expr->op()) { |
| 1489 case Token::COMMA: | 1489 case Token::COMMA: |
| 1490 VisitForEffect(expr->left()); | 1490 VisitForEffect(expr->left()); |
| 1491 Visit(expr->right()); | 1491 Visit(expr->right()); |
| 1492 break; | 1492 break; |
| 1493 | 1493 |
| 1494 case Token::OR: | 1494 case Token::OR: |
| 1495 case Token::AND: | 1495 case Token::AND: |
| 1496 EmitLogicalOperation(expr); | 1496 EmitLogicalOperation(expr); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1511 VisitForValue(expr->right(), kAccumulator); | 1511 VisitForValue(expr->right(), kAccumulator); |
| 1512 EmitBinaryOp(expr->op(), context_); | 1512 EmitBinaryOp(expr->op(), context_); |
| 1513 break; | 1513 break; |
| 1514 | 1514 |
| 1515 default: | 1515 default: |
| 1516 UNREACHABLE(); | 1516 UNREACHABLE(); |
| 1517 } | 1517 } |
| 1518 } | 1518 } |
| 1519 | 1519 |
| 1520 | 1520 |
| 1521 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1521 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 1522 Comment cmnt(masm_, "[ CompareOperation"); | 1522 Comment cmnt(masm_, "[ CompareOperation"); |
| 1523 | 1523 |
| 1524 // Always perform the comparison for its control flow. Pack the result | 1524 // Always perform the comparison for its control flow. Pack the result |
| 1525 // into the expression's context after the comparison is performed. | 1525 // into the expression's context after the comparison is performed. |
| 1526 Label materialize_true, materialize_false, done; | 1526 Label materialize_true, materialize_false, done; |
| 1527 // Initially assume we are in a test context. | 1527 // Initially assume we are in a test context. |
| 1528 Label* if_true = true_label_; | 1528 Label* if_true = true_label_; |
| 1529 Label* if_false = false_label_; | 1529 Label* if_false = false_label_; |
| 1530 switch (context_) { | 1530 switch (context_) { |
| 1531 case Expression::kUninitialized: | 1531 case Expression::kUninitialized: |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1626 __ jmp(if_false); | 1626 __ jmp(if_false); |
| 1627 } | 1627 } |
| 1628 } | 1628 } |
| 1629 | 1629 |
| 1630 // Convert the result of the comparison into one expected for this | 1630 // Convert the result of the comparison into one expected for this |
| 1631 // expression's context. | 1631 // expression's context. |
| 1632 Apply(context_, if_true, if_false); | 1632 Apply(context_, if_true, if_false); |
| 1633 } | 1633 } |
| 1634 | 1634 |
| 1635 | 1635 |
| 1636 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1636 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 1637 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1637 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1638 Apply(context_, r0); | 1638 Apply(context_, r0); |
| 1639 } | 1639 } |
| 1640 | 1640 |
| 1641 | 1641 |
| 1642 Register FastCodeGenerator::result_register() { return r0; } | 1642 Register FullCodeGenerator::result_register() { return r0; } |
| 1643 | 1643 |
| 1644 | 1644 |
| 1645 Register FastCodeGenerator::context_register() { return cp; } | 1645 Register FullCodeGenerator::context_register() { return cp; } |
| 1646 | 1646 |
| 1647 | 1647 |
| 1648 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1648 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| 1649 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 1649 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| 1650 __ str(value, MemOperand(fp, frame_offset)); | 1650 __ str(value, MemOperand(fp, frame_offset)); |
| 1651 } | 1651 } |
| 1652 | 1652 |
| 1653 | 1653 |
| 1654 void FastCodeGenerator::LoadContextField(Register dst, int context_index) { | 1654 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
| 1655 __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index)); | 1655 __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index)); |
| 1656 } | 1656 } |
| 1657 | 1657 |
| 1658 | 1658 |
| 1659 // ---------------------------------------------------------------------------- | 1659 // ---------------------------------------------------------------------------- |
| 1660 // Non-local control flow support. | 1660 // Non-local control flow support. |
| 1661 | 1661 |
| 1662 void FastCodeGenerator::EnterFinallyBlock() { | 1662 void FullCodeGenerator::EnterFinallyBlock() { |
| 1663 ASSERT(!result_register().is(r1)); | 1663 ASSERT(!result_register().is(r1)); |
| 1664 // Store result register while executing finally block. | 1664 // Store result register while executing finally block. |
| 1665 __ push(result_register()); | 1665 __ push(result_register()); |
| 1666 // Cook return address in link register to stack (smi encoded Code* delta) | 1666 // Cook return address in link register to stack (smi encoded Code* delta) |
| 1667 __ sub(r1, lr, Operand(masm_->CodeObject())); | 1667 __ sub(r1, lr, Operand(masm_->CodeObject())); |
| 1668 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1668 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
| 1669 ASSERT_EQ(0, kSmiTag); | 1669 ASSERT_EQ(0, kSmiTag); |
| 1670 __ add(r1, r1, Operand(r1)); // Convert to smi. | 1670 __ add(r1, r1, Operand(r1)); // Convert to smi. |
| 1671 __ push(r1); | 1671 __ push(r1); |
| 1672 } | 1672 } |
| 1673 | 1673 |
| 1674 | 1674 |
| 1675 void FastCodeGenerator::ExitFinallyBlock() { | 1675 void FullCodeGenerator::ExitFinallyBlock() { |
| 1676 ASSERT(!result_register().is(r1)); | 1676 ASSERT(!result_register().is(r1)); |
| 1677 // Restore result register from stack. | 1677 // Restore result register from stack. |
| 1678 __ pop(r1); | 1678 __ pop(r1); |
| 1679 // Uncook return address and return. | 1679 // Uncook return address and return. |
| 1680 __ pop(result_register()); | 1680 __ pop(result_register()); |
| 1681 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1681 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
| 1682 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1682 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 1683 __ add(pc, r1, Operand(masm_->CodeObject())); | 1683 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 1684 } | 1684 } |
| 1685 | 1685 |
| 1686 | 1686 |
| 1687 #undef __ | 1687 #undef __ |
| 1688 | 1688 |
| 1689 } } // namespace v8::internal | 1689 } } // namespace v8::internal |
| OLD | NEW |