| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/full-codegen/full-codegen.h" | 5 #include "src/full-codegen/full-codegen.h" |
| 6 | 6 |
| 7 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
| 8 #include "src/ast/ast-numbering.h" | 8 #include "src/ast/ast-numbering.h" |
| 9 #include "src/ast/prettyprinter.h" | 9 #include "src/ast/prettyprinter.h" |
| 10 #include "src/ast/scopeinfo.h" | 10 #include "src/ast/scopeinfo.h" |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 void FullCodeGenerator::EffectContext::Plug(Register reg) const { | 265 void FullCodeGenerator::EffectContext::Plug(Register reg) const { |
| 266 } | 266 } |
| 267 | 267 |
| 268 | 268 |
| 269 void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const { | 269 void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const { |
| 270 __ Move(result_register(), reg); | 270 __ Move(result_register(), reg); |
| 271 } | 271 } |
| 272 | 272 |
| 273 | 273 |
| 274 void FullCodeGenerator::StackValueContext::Plug(Register reg) const { | 274 void FullCodeGenerator::StackValueContext::Plug(Register reg) const { |
| 275 __ Push(reg); | 275 codegen()->PushOperand(reg); |
| 276 } | 276 } |
| 277 | 277 |
| 278 | 278 |
| 279 void FullCodeGenerator::TestContext::Plug(Register reg) const { | 279 void FullCodeGenerator::TestContext::Plug(Register reg) const { |
| 280 // For simplicity we always test the accumulator register. | 280 // For simplicity we always test the accumulator register. |
| 281 __ Move(result_register(), reg); | 281 __ Move(result_register(), reg); |
| 282 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 282 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 283 codegen()->DoTest(this); | 283 codegen()->DoTest(this); |
| 284 } | 284 } |
| 285 | 285 |
| 286 | 286 |
| 287 void FullCodeGenerator::EffectContext::Plug(bool flag) const {} | 287 void FullCodeGenerator::EffectContext::Plug(bool flag) const {} |
| 288 | 288 |
| 289 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| 290 Register reg) const { |
| 291 DCHECK(count > 0); |
| 292 codegen()->DropOperands(count); |
| 293 } |
| 294 |
| 295 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
| 296 int count, Register reg) const { |
| 297 DCHECK(count > 0); |
| 298 codegen()->DropOperands(count); |
| 299 __ Move(result_register(), reg); |
| 300 } |
| 301 |
| 302 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
| 303 Register reg) const { |
| 304 DCHECK(count > 0); |
| 305 // For simplicity we always test the accumulator register. |
| 306 codegen()->DropOperands(count); |
| 307 __ Move(result_register(), reg); |
| 308 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 309 codegen()->DoTest(this); |
| 310 } |
| 289 | 311 |
| 290 void FullCodeGenerator::EffectContext::PlugTOS() const { | 312 void FullCodeGenerator::EffectContext::PlugTOS() const { |
| 291 __ Drop(1); | 313 codegen()->DropOperands(1); |
| 292 } | 314 } |
| 293 | 315 |
| 294 | 316 |
| 295 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const { | 317 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const { |
| 296 __ Pop(result_register()); | 318 codegen()->PopOperand(result_register()); |
| 297 } | 319 } |
| 298 | 320 |
| 299 | 321 |
| 300 void FullCodeGenerator::StackValueContext::PlugTOS() const { | 322 void FullCodeGenerator::StackValueContext::PlugTOS() const { |
| 301 } | 323 } |
| 302 | 324 |
| 303 | 325 |
| 304 void FullCodeGenerator::TestContext::PlugTOS() const { | 326 void FullCodeGenerator::TestContext::PlugTOS() const { |
| 305 // For simplicity we always test the accumulator register. | 327 // For simplicity we always test the accumulator register. |
| 306 __ Pop(result_register()); | 328 codegen()->PopOperand(result_register()); |
| 307 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 329 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 308 codegen()->DoTest(this); | 330 codegen()->DoTest(this); |
| 309 } | 331 } |
| 310 | 332 |
| 311 | 333 |
| 312 void FullCodeGenerator::EffectContext::PrepareTest( | 334 void FullCodeGenerator::EffectContext::PrepareTest( |
| 313 Label* materialize_true, | 335 Label* materialize_true, |
| 314 Label* materialize_false, | 336 Label* materialize_false, |
| 315 Label** if_true, | 337 Label** if_true, |
| 316 Label** if_false, | 338 Label** if_false, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 } | 448 } |
| 427 | 449 |
| 428 | 450 |
| 429 int FullCodeGenerator::DeclareGlobalsFlags() { | 451 int FullCodeGenerator::DeclareGlobalsFlags() { |
| 430 DCHECK(DeclareGlobalsLanguageMode::is_valid(language_mode())); | 452 DCHECK(DeclareGlobalsLanguageMode::is_valid(language_mode())); |
| 431 return DeclareGlobalsEvalFlag::encode(is_eval()) | | 453 return DeclareGlobalsEvalFlag::encode(is_eval()) | |
| 432 DeclareGlobalsNativeFlag::encode(is_native()) | | 454 DeclareGlobalsNativeFlag::encode(is_native()) | |
| 433 DeclareGlobalsLanguageMode::encode(language_mode()); | 455 DeclareGlobalsLanguageMode::encode(language_mode()); |
| 434 } | 456 } |
| 435 | 457 |
| 458 void FullCodeGenerator::PushOperand(Handle<Object> handle) { |
| 459 OperandStackDepthIncrement(1); |
| 460 __ Push(handle); |
| 461 } |
| 462 |
| 463 void FullCodeGenerator::PushOperand(Smi* smi) { |
| 464 OperandStackDepthIncrement(1); |
| 465 __ Push(smi); |
| 466 } |
| 467 |
| 468 void FullCodeGenerator::PushOperand(Register reg) { |
| 469 OperandStackDepthIncrement(1); |
| 470 __ Push(reg); |
| 471 } |
| 472 |
| 473 void FullCodeGenerator::PopOperand(Register reg) { |
| 474 OperandStackDepthDecrement(1); |
| 475 __ Pop(reg); |
| 476 } |
| 477 |
| 478 void FullCodeGenerator::DropOperands(int count) { |
| 479 OperandStackDepthDecrement(count); |
| 480 __ Drop(count); |
| 481 } |
| 482 |
| 483 void FullCodeGenerator::CallRuntimeWithOperands(Runtime::FunctionId id) { |
| 484 OperandStackDepthDecrement(Runtime::FunctionForId(id)->nargs); |
| 485 __ CallRuntime(id); |
| 486 } |
| 487 |
| 488 void FullCodeGenerator::OperandStackDepthIncrement(int count) { |
| 489 DCHECK_GE(count, 0); |
| 490 DCHECK_GE(operand_stack_depth_, 0); |
| 491 operand_stack_depth_ += count; |
| 492 } |
| 493 |
| 494 void FullCodeGenerator::OperandStackDepthDecrement(int count) { |
| 495 DCHECK_GE(count, 0); |
| 496 DCHECK_GE(operand_stack_depth_, count); |
| 497 operand_stack_depth_ -= count; |
| 498 } |
| 436 | 499 |
| 437 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { | 500 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
| 438 // Load the arguments on the stack and call the stub. | 501 // Load the arguments on the stack and call the stub. |
| 439 SubStringStub stub(isolate()); | 502 SubStringStub stub(isolate()); |
| 440 ZoneList<Expression*>* args = expr->arguments(); | 503 ZoneList<Expression*>* args = expr->arguments(); |
| 441 DCHECK(args->length() == 3); | 504 DCHECK(args->length() == 3); |
| 442 VisitForStackValue(args->at(0)); | 505 VisitForStackValue(args->at(0)); |
| 443 VisitForStackValue(args->at(1)); | 506 VisitForStackValue(args->at(1)); |
| 444 VisitForStackValue(args->at(2)); | 507 VisitForStackValue(args->at(2)); |
| 445 __ CallStub(&stub); | 508 __ CallStub(&stub); |
| 509 OperandStackDepthDecrement(3); |
| 446 context()->Plug(result_register()); | 510 context()->Plug(result_register()); |
| 447 } | 511 } |
| 448 | 512 |
| 449 | 513 |
| 450 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { | 514 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
| 451 // Load the arguments on the stack and call the stub. | 515 // Load the arguments on the stack and call the stub. |
| 452 RegExpExecStub stub(isolate()); | 516 RegExpExecStub stub(isolate()); |
| 453 ZoneList<Expression*>* args = expr->arguments(); | 517 ZoneList<Expression*>* args = expr->arguments(); |
| 454 DCHECK(args->length() == 4); | 518 DCHECK(args->length() == 4); |
| 455 VisitForStackValue(args->at(0)); | 519 VisitForStackValue(args->at(0)); |
| 456 VisitForStackValue(args->at(1)); | 520 VisitForStackValue(args->at(1)); |
| 457 VisitForStackValue(args->at(2)); | 521 VisitForStackValue(args->at(2)); |
| 458 VisitForStackValue(args->at(3)); | 522 VisitForStackValue(args->at(3)); |
| 459 __ CallStub(&stub); | 523 __ CallStub(&stub); |
| 524 OperandStackDepthDecrement(4); |
| 460 context()->Plug(result_register()); | 525 context()->Plug(result_register()); |
| 461 } | 526 } |
| 462 | 527 |
| 463 | 528 |
| 464 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 529 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
| 465 // Load the arguments on the stack and call the runtime function. | 530 // Load the arguments on the stack and call the runtime function. |
| 531 MathPowStub stub(isolate(), MathPowStub::ON_STACK); |
| 466 ZoneList<Expression*>* args = expr->arguments(); | 532 ZoneList<Expression*>* args = expr->arguments(); |
| 467 DCHECK(args->length() == 2); | 533 DCHECK(args->length() == 2); |
| 468 VisitForStackValue(args->at(0)); | 534 VisitForStackValue(args->at(0)); |
| 469 VisitForStackValue(args->at(1)); | 535 VisitForStackValue(args->at(1)); |
| 470 | |
| 471 MathPowStub stub(isolate(), MathPowStub::ON_STACK); | |
| 472 __ CallStub(&stub); | 536 __ CallStub(&stub); |
| 537 OperandStackDepthDecrement(2); |
| 473 context()->Plug(result_register()); | 538 context()->Plug(result_register()); |
| 474 } | 539 } |
| 475 | 540 |
| 476 | 541 |
| 477 void FullCodeGenerator::EmitIntrinsicAsStubCall(CallRuntime* expr, | 542 void FullCodeGenerator::EmitIntrinsicAsStubCall(CallRuntime* expr, |
| 478 const Callable& callable) { | 543 const Callable& callable) { |
| 479 ZoneList<Expression*>* args = expr->arguments(); | 544 ZoneList<Expression*>* args = expr->arguments(); |
| 480 int param_count = callable.descriptor().GetRegisterParameterCount(); | 545 int param_count = callable.descriptor().GetRegisterParameterCount(); |
| 481 DCHECK_EQ(args->length(), param_count); | 546 DCHECK_EQ(args->length(), param_count); |
| 482 | 547 |
| 483 if (param_count > 0) { | 548 if (param_count > 0) { |
| 484 int last = param_count - 1; | 549 int last = param_count - 1; |
| 485 // Put all but last arguments on stack. | 550 // Put all but last arguments on stack. |
| 486 for (int i = 0; i < last; i++) { | 551 for (int i = 0; i < last; i++) { |
| 487 VisitForStackValue(args->at(i)); | 552 VisitForStackValue(args->at(i)); |
| 488 } | 553 } |
| 489 // The last argument goes to the accumulator. | 554 // The last argument goes to the accumulator. |
| 490 VisitForAccumulatorValue(args->at(last)); | 555 VisitForAccumulatorValue(args->at(last)); |
| 491 | 556 |
| 492 // Move the arguments to the registers, as required by the stub. | 557 // Move the arguments to the registers, as required by the stub. |
| 493 __ Move(callable.descriptor().GetRegisterParameter(last), | 558 __ Move(callable.descriptor().GetRegisterParameter(last), |
| 494 result_register()); | 559 result_register()); |
| 495 for (int i = last; i-- > 0;) { | 560 for (int i = last; i-- > 0;) { |
| 496 __ Pop(callable.descriptor().GetRegisterParameter(i)); | 561 PopOperand(callable.descriptor().GetRegisterParameter(i)); |
| 497 } | 562 } |
| 498 } | 563 } |
| 499 __ Call(callable.code(), RelocInfo::CODE_TARGET); | 564 __ Call(callable.code(), RelocInfo::CODE_TARGET); |
| 500 context()->Plug(result_register()); | 565 context()->Plug(result_register()); |
| 501 } | 566 } |
| 502 | 567 |
| 503 | 568 |
| 504 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { | 569 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 505 EmitIntrinsicAsStubCall(expr, CodeFactory::NumberToString(isolate())); | 570 EmitIntrinsicAsStubCall(expr, CodeFactory::NumberToString(isolate())); |
| 506 } | 571 } |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 DCHECK_EQ(0, context_length); | 1001 DCHECK_EQ(0, context_length); |
| 937 current->AsTryFinally()->deferred_commands()->RecordReturn(); | 1002 current->AsTryFinally()->deferred_commands()->RecordReturn(); |
| 938 return; | 1003 return; |
| 939 } | 1004 } |
| 940 current = current->Exit(&stack_depth, &context_length); | 1005 current = current->Exit(&stack_depth, &context_length); |
| 941 } | 1006 } |
| 942 __ Drop(stack_depth); | 1007 __ Drop(stack_depth); |
| 943 EmitReturnSequence(); | 1008 EmitReturnSequence(); |
| 944 } | 1009 } |
| 945 | 1010 |
| 1011 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
| 1012 // Stack: receiver, home_object |
| 1013 SetExpressionPosition(prop); |
| 1014 Literal* key = prop->key()->AsLiteral(); |
| 1015 DCHECK(!key->value()->IsSmi()); |
| 1016 DCHECK(prop->IsSuperAccess()); |
| 1017 |
| 1018 PushOperand(key->value()); |
| 1019 CallRuntimeWithOperands(Runtime::kLoadFromSuper); |
| 1020 } |
| 1021 |
| 1022 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1023 SetExpressionPosition(prop); |
| 1024 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); |
| 1025 __ Move(LoadDescriptor::SlotRegister(), |
| 1026 SmiFromSlot(prop->PropertyFeedbackSlot())); |
| 1027 CallIC(ic); |
| 1028 } |
| 1029 |
| 1030 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
| 1031 // Stack: receiver, home_object, key. |
| 1032 SetExpressionPosition(prop); |
| 1033 CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper); |
| 1034 } |
| 946 | 1035 |
| 947 void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property, | 1036 void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property, |
| 948 BailoutId bailout_id) { | 1037 BailoutId bailout_id) { |
| 949 VisitForStackValue(property->key()); | 1038 VisitForStackValue(property->key()); |
| 950 __ CallRuntime(Runtime::kToName); | 1039 CallRuntimeWithOperands(Runtime::kToName); |
| 951 PrepareForBailoutForId(bailout_id, NO_REGISTERS); | 1040 PrepareForBailoutForId(bailout_id, NO_REGISTERS); |
| 952 __ Push(result_register()); | 1041 PushOperand(result_register()); |
| 953 } | 1042 } |
| 954 | 1043 |
| 955 | 1044 |
| 956 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 1045 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 957 Comment cmnt(masm_, "[ ReturnStatement"); | 1046 Comment cmnt(masm_, "[ ReturnStatement"); |
| 958 SetStatementPosition(stmt); | 1047 SetStatementPosition(stmt); |
| 959 Expression* expr = stmt->expression(); | 1048 Expression* expr = stmt->expression(); |
| 960 VisitForAccumulatorValue(expr); | 1049 VisitForAccumulatorValue(expr); |
| 961 EmitUnwindAndReturn(); | 1050 EmitUnwindAndReturn(); |
| 962 } | 1051 } |
| 963 | 1052 |
| 964 | 1053 |
| 965 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { | 1054 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 966 Comment cmnt(masm_, "[ WithStatement"); | 1055 Comment cmnt(masm_, "[ WithStatement"); |
| 967 SetStatementPosition(stmt); | 1056 SetStatementPosition(stmt); |
| 968 | 1057 |
| 969 VisitForAccumulatorValue(stmt->expression()); | 1058 VisitForAccumulatorValue(stmt->expression()); |
| 970 Callable callable = CodeFactory::ToObject(isolate()); | 1059 Callable callable = CodeFactory::ToObject(isolate()); |
| 971 __ Move(callable.descriptor().GetRegisterParameter(0), result_register()); | 1060 __ Move(callable.descriptor().GetRegisterParameter(0), result_register()); |
| 972 __ Call(callable.code(), RelocInfo::CODE_TARGET); | 1061 __ Call(callable.code(), RelocInfo::CODE_TARGET); |
| 973 PrepareForBailoutForId(stmt->ToObjectId(), NO_REGISTERS); | 1062 PrepareForBailoutForId(stmt->ToObjectId(), NO_REGISTERS); |
| 974 __ Push(result_register()); | 1063 PushOperand(result_register()); |
| 975 PushFunctionArgumentForContextAllocation(); | 1064 PushFunctionArgumentForContextAllocation(); |
| 976 __ CallRuntime(Runtime::kPushWithContext); | 1065 CallRuntimeWithOperands(Runtime::kPushWithContext); |
| 977 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 1066 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 978 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 1067 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 979 | 1068 |
| 980 Scope* saved_scope = scope(); | 1069 Scope* saved_scope = scope(); |
| 981 scope_ = stmt->scope(); | 1070 scope_ = stmt->scope(); |
| 982 { WithOrCatch body(this); | 1071 { WithOrCatch body(this); |
| 983 Visit(stmt->statement()); | 1072 Visit(stmt->statement()); |
| 984 } | 1073 } |
| 985 scope_ = saved_scope; | 1074 scope_ = saved_scope; |
| 986 | 1075 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1159 // result register. | 1248 // result register. |
| 1160 | 1249 |
| 1161 Label try_entry, handler_entry, exit; | 1250 Label try_entry, handler_entry, exit; |
| 1162 __ jmp(&try_entry); | 1251 __ jmp(&try_entry); |
| 1163 __ bind(&handler_entry); | 1252 __ bind(&handler_entry); |
| 1164 ClearPendingMessage(); | 1253 ClearPendingMessage(); |
| 1165 | 1254 |
| 1166 // Exception handler code, the exception is in the result register. | 1255 // Exception handler code, the exception is in the result register. |
| 1167 // Extend the context before executing the catch block. | 1256 // Extend the context before executing the catch block. |
| 1168 { Comment cmnt(masm_, "[ Extend catch context"); | 1257 { Comment cmnt(masm_, "[ Extend catch context"); |
| 1169 __ Push(stmt->variable()->name()); | 1258 PushOperand(stmt->variable()->name()); |
| 1170 __ Push(result_register()); | 1259 PushOperand(result_register()); |
| 1171 PushFunctionArgumentForContextAllocation(); | 1260 PushFunctionArgumentForContextAllocation(); |
| 1172 __ CallRuntime(Runtime::kPushCatchContext); | 1261 CallRuntimeWithOperands(Runtime::kPushCatchContext); |
| 1173 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1262 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1174 context_register()); | 1263 context_register()); |
| 1175 } | 1264 } |
| 1176 | 1265 |
| 1177 Scope* saved_scope = scope(); | 1266 Scope* saved_scope = scope(); |
| 1178 scope_ = stmt->scope(); | 1267 scope_ = stmt->scope(); |
| 1179 DCHECK(scope_->declarations()->is_empty()); | 1268 DCHECK(scope_->declarations()->is_empty()); |
| 1180 { WithOrCatch catch_body(this); | 1269 { WithOrCatch catch_body(this); |
| 1181 Visit(stmt->catch_block()); | 1270 Visit(stmt->catch_block()); |
| 1182 } | 1271 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 // value in the result register with one that's safe for GC because the | 1339 // value in the result register with one that's safe for GC because the |
| 1251 // finally block will unconditionally preserve the result register on the | 1340 // finally block will unconditionally preserve the result register on the |
| 1252 // stack. | 1341 // stack. |
| 1253 ClearAccumulator(); | 1342 ClearAccumulator(); |
| 1254 deferred.EmitFallThrough(); | 1343 deferred.EmitFallThrough(); |
| 1255 // Fall through to the finally block. | 1344 // Fall through to the finally block. |
| 1256 | 1345 |
| 1257 // Finally block implementation. | 1346 // Finally block implementation. |
| 1258 __ bind(&finally_entry); | 1347 __ bind(&finally_entry); |
| 1259 Comment cmnt_finally(masm(), "[ Finally block"); | 1348 Comment cmnt_finally(masm(), "[ Finally block"); |
| 1349 OperandStackDepthIncrement(2); // Token and accumulator are on stack. |
| 1260 EnterFinallyBlock(); | 1350 EnterFinallyBlock(); |
| 1261 { | 1351 { |
| 1262 Finally finally_body(this); | 1352 Finally finally_body(this); |
| 1263 Visit(stmt->finally_block()); | 1353 Visit(stmt->finally_block()); |
| 1264 } | 1354 } |
| 1265 ExitFinallyBlock(); // Return to the calling code. | 1355 ExitFinallyBlock(); |
| 1356 OperandStackDepthDecrement(2); // Token and accumulator were on stack. |
| 1266 | 1357 |
| 1267 { | 1358 { |
| 1268 Comment cmnt_deferred(masm(), "[ Post-finally dispatch"); | 1359 Comment cmnt_deferred(masm(), "[ Post-finally dispatch"); |
| 1269 deferred.EmitCommands(); | 1360 deferred.EmitCommands(); // Return to the calling code. |
| 1270 } | 1361 } |
| 1271 } | 1362 } |
| 1272 | 1363 |
| 1273 | 1364 |
| 1274 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1365 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1275 Comment cmnt(masm_, "[ DebuggerStatement"); | 1366 Comment cmnt(masm_, "[ DebuggerStatement"); |
| 1276 SetStatementPosition(stmt); | 1367 SetStatementPosition(stmt); |
| 1277 | 1368 |
| 1278 __ DebugBreak(); | 1369 __ DebugBreak(); |
| 1279 // Ignore the return value. | 1370 // Ignore the return value. |
| 1280 | 1371 |
| 1281 PrepareForBailoutForId(stmt->DebugBreakId(), NO_REGISTERS); | 1372 PrepareForBailoutForId(stmt->DebugBreakId(), NO_REGISTERS); |
| 1282 } | 1373 } |
| 1283 | 1374 |
| 1284 | 1375 |
| 1285 void FullCodeGenerator::VisitCaseClause(CaseClause* clause) { | 1376 void FullCodeGenerator::VisitCaseClause(CaseClause* clause) { |
| 1286 UNREACHABLE(); | 1377 UNREACHABLE(); |
| 1287 } | 1378 } |
| 1288 | 1379 |
| 1289 | 1380 |
| 1290 void FullCodeGenerator::VisitConditional(Conditional* expr) { | 1381 void FullCodeGenerator::VisitConditional(Conditional* expr) { |
| 1291 Comment cmnt(masm_, "[ Conditional"); | 1382 Comment cmnt(masm_, "[ Conditional"); |
| 1292 Label true_case, false_case, done; | 1383 Label true_case, false_case, done; |
| 1293 VisitForControl(expr->condition(), &true_case, &false_case, &true_case); | 1384 VisitForControl(expr->condition(), &true_case, &false_case, &true_case); |
| 1294 | 1385 |
| 1386 int original_stack_depth = operand_stack_depth_; |
| 1295 PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS); | 1387 PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS); |
| 1296 __ bind(&true_case); | 1388 __ bind(&true_case); |
| 1297 SetExpressionPosition(expr->then_expression()); | 1389 SetExpressionPosition(expr->then_expression()); |
| 1298 if (context()->IsTest()) { | 1390 if (context()->IsTest()) { |
| 1299 const TestContext* for_test = TestContext::cast(context()); | 1391 const TestContext* for_test = TestContext::cast(context()); |
| 1300 VisitForControl(expr->then_expression(), | 1392 VisitForControl(expr->then_expression(), |
| 1301 for_test->true_label(), | 1393 for_test->true_label(), |
| 1302 for_test->false_label(), | 1394 for_test->false_label(), |
| 1303 NULL); | 1395 NULL); |
| 1304 } else { | 1396 } else { |
| 1305 VisitInDuplicateContext(expr->then_expression()); | 1397 VisitInDuplicateContext(expr->then_expression()); |
| 1306 __ jmp(&done); | 1398 __ jmp(&done); |
| 1307 } | 1399 } |
| 1308 | 1400 |
| 1401 operand_stack_depth_ = original_stack_depth; |
| 1309 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); | 1402 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); |
| 1310 __ bind(&false_case); | 1403 __ bind(&false_case); |
| 1311 SetExpressionPosition(expr->else_expression()); | 1404 SetExpressionPosition(expr->else_expression()); |
| 1312 VisitInDuplicateContext(expr->else_expression()); | 1405 VisitInDuplicateContext(expr->else_expression()); |
| 1313 // If control flow falls through Visit, merge it with true case here. | 1406 // If control flow falls through Visit, merge it with true case here. |
| 1314 if (!context()->IsTest()) { | 1407 if (!context()->IsTest()) { |
| 1315 __ bind(&done); | 1408 __ bind(&done); |
| 1316 } | 1409 } |
| 1317 } | 1410 } |
| 1318 | 1411 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1340 void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { | 1433 void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { |
| 1341 Comment cmnt(masm_, "[ ClassLiteral"); | 1434 Comment cmnt(masm_, "[ ClassLiteral"); |
| 1342 | 1435 |
| 1343 { | 1436 { |
| 1344 EnterBlockScopeIfNeeded block_scope_state( | 1437 EnterBlockScopeIfNeeded block_scope_state( |
| 1345 this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId()); | 1438 this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId()); |
| 1346 | 1439 |
| 1347 if (lit->extends() != NULL) { | 1440 if (lit->extends() != NULL) { |
| 1348 VisitForStackValue(lit->extends()); | 1441 VisitForStackValue(lit->extends()); |
| 1349 } else { | 1442 } else { |
| 1350 __ Push(isolate()->factory()->the_hole_value()); | 1443 PushOperand(isolate()->factory()->the_hole_value()); |
| 1351 } | 1444 } |
| 1352 | 1445 |
| 1353 VisitForStackValue(lit->constructor()); | 1446 VisitForStackValue(lit->constructor()); |
| 1354 | 1447 |
| 1355 __ Push(Smi::FromInt(lit->start_position())); | 1448 PushOperand(Smi::FromInt(lit->start_position())); |
| 1356 __ Push(Smi::FromInt(lit->end_position())); | 1449 PushOperand(Smi::FromInt(lit->end_position())); |
| 1357 | 1450 |
| 1358 __ CallRuntime(Runtime::kDefineClass); | 1451 CallRuntimeWithOperands(Runtime::kDefineClass); |
| 1359 PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG); | 1452 PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG); |
| 1360 __ Push(result_register()); | 1453 PushOperand(result_register()); |
| 1361 | 1454 |
| 1362 // Load the "prototype" from the constructor. | 1455 // Load the "prototype" from the constructor. |
| 1363 __ Move(LoadDescriptor::ReceiverRegister(), result_register()); | 1456 __ Move(LoadDescriptor::ReceiverRegister(), result_register()); |
| 1364 __ LoadRoot(LoadDescriptor::NameRegister(), | 1457 __ LoadRoot(LoadDescriptor::NameRegister(), |
| 1365 Heap::kprototype_stringRootIndex); | 1458 Heap::kprototype_stringRootIndex); |
| 1366 __ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot())); | 1459 __ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot())); |
| 1367 CallLoadIC(NOT_INSIDE_TYPEOF); | 1460 CallLoadIC(NOT_INSIDE_TYPEOF); |
| 1368 PrepareForBailoutForId(lit->PrototypeId(), TOS_REG); | 1461 PrepareForBailoutForId(lit->PrototypeId(), TOS_REG); |
| 1369 __ Push(result_register()); | 1462 PushOperand(result_register()); |
| 1370 | 1463 |
| 1371 EmitClassDefineProperties(lit); | 1464 EmitClassDefineProperties(lit); |
| 1372 | 1465 |
| 1373 // Set both the prototype and constructor to have fast properties, and also | 1466 // Set both the prototype and constructor to have fast properties, and also |
| 1374 // freeze them in strong mode. | 1467 // freeze them in strong mode. |
| 1375 __ CallRuntime(Runtime::kFinalizeClassDefinition); | 1468 CallRuntimeWithOperands(Runtime::kFinalizeClassDefinition); |
| 1376 | 1469 |
| 1377 if (lit->class_variable_proxy() != nullptr) { | 1470 if (lit->class_variable_proxy() != nullptr) { |
| 1378 EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT, | 1471 EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT, |
| 1379 lit->ProxySlot()); | 1472 lit->ProxySlot()); |
| 1380 } | 1473 } |
| 1381 } | 1474 } |
| 1382 | 1475 |
| 1383 context()->Plug(result_register()); | 1476 context()->Plug(result_register()); |
| 1384 } | 1477 } |
| 1385 | 1478 |
| 1386 | 1479 |
| 1387 void FullCodeGenerator::VisitNativeFunctionLiteral( | 1480 void FullCodeGenerator::VisitNativeFunctionLiteral( |
| 1388 NativeFunctionLiteral* expr) { | 1481 NativeFunctionLiteral* expr) { |
| 1389 Comment cmnt(masm_, "[ NativeFunctionLiteral"); | 1482 Comment cmnt(masm_, "[ NativeFunctionLiteral"); |
| 1390 Handle<SharedFunctionInfo> shared = | 1483 Handle<SharedFunctionInfo> shared = |
| 1391 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); | 1484 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); |
| 1392 EmitNewClosure(shared, false); | 1485 EmitNewClosure(shared, false); |
| 1393 } | 1486 } |
| 1394 | 1487 |
| 1395 | 1488 |
| 1396 void FullCodeGenerator::VisitThrow(Throw* expr) { | 1489 void FullCodeGenerator::VisitThrow(Throw* expr) { |
| 1397 Comment cmnt(masm_, "[ Throw"); | 1490 Comment cmnt(masm_, "[ Throw"); |
| 1398 VisitForStackValue(expr->exception()); | 1491 VisitForStackValue(expr->exception()); |
| 1399 SetExpressionPosition(expr); | 1492 SetExpressionPosition(expr); |
| 1400 __ CallRuntime(Runtime::kThrow); | 1493 CallRuntimeWithOperands(Runtime::kThrow); |
| 1401 // Never returns here. | 1494 // Never returns here. |
| 1495 |
| 1496 // Even though this expression doesn't produce a value, we need to simulate |
| 1497 // plugging of the value context to ensure stack depth tracking is in sync. |
| 1498 if (context()->IsStackValue()) OperandStackDepthIncrement(1); |
| 1402 } | 1499 } |
| 1403 | 1500 |
| 1404 | 1501 |
| 1405 void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) { | 1502 void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) { |
| 1406 HandlerTableEntry* entry = &handler_table_[handler_index]; | 1503 HandlerTableEntry* entry = &handler_table_[handler_index]; |
| 1407 entry->range_start = masm()->pc_offset(); | 1504 entry->range_start = masm()->pc_offset(); |
| 1408 entry->handler_offset = handler->pos(); | 1505 entry->handler_offset = handler->pos(); |
| 1409 entry->try_catch_depth = try_catch_depth_; | 1506 entry->try_catch_depth = try_catch_depth_; |
| 1507 entry->stack_depth = operand_stack_depth_; |
| 1410 | 1508 |
| 1411 // Determine expression stack depth of try statement. | 1509 // We are using the operand stack depth, check for accuracy. |
| 1412 int stack_depth = info_->scope()->num_stack_slots(); // Include stack locals. | 1510 EmitOperandStackDepthCheck(); |
| 1413 for (NestedStatement* current = nesting_stack_; current != NULL; /*nop*/) { | |
| 1414 current = current->AccumulateDepth(&stack_depth); | |
| 1415 } | |
| 1416 entry->stack_depth = stack_depth; | |
| 1417 | 1511 |
| 1418 // Push context onto operand stack. | 1512 // Push context onto operand stack. |
| 1419 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | 1513 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
| 1420 __ Push(context_register()); | 1514 PushOperand(context_register()); |
| 1421 } | 1515 } |
| 1422 | 1516 |
| 1423 | 1517 |
| 1424 void FullCodeGenerator::ExitTryBlock(int handler_index) { | 1518 void FullCodeGenerator::ExitTryBlock(int handler_index) { |
| 1425 HandlerTableEntry* entry = &handler_table_[handler_index]; | 1519 HandlerTableEntry* entry = &handler_table_[handler_index]; |
| 1426 entry->range_end = masm()->pc_offset(); | 1520 entry->range_end = masm()->pc_offset(); |
| 1427 | 1521 |
| 1428 // Drop context from operand stack. | 1522 // Drop context from operand stack. |
| 1429 __ Drop(TryBlockConstant::kElementCount); | 1523 DropOperands(TryBlockConstant::kElementCount); |
| 1430 } | 1524 } |
| 1431 | 1525 |
| 1432 | 1526 |
| 1433 void FullCodeGenerator::VisitCall(Call* expr) { | 1527 void FullCodeGenerator::VisitCall(Call* expr) { |
| 1434 #ifdef DEBUG | 1528 #ifdef DEBUG |
| 1435 // We want to verify that RecordJSReturnSite gets called on all paths | 1529 // We want to verify that RecordJSReturnSite gets called on all paths |
| 1436 // through this function. Avoid early returns. | 1530 // through this function. Avoid early returns. |
| 1437 expr->return_is_recorded_ = false; | 1531 expr->return_is_recorded_ = false; |
| 1438 #endif | 1532 #endif |
| 1439 | 1533 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 break; | 1566 break; |
| 1473 case Call::KEYED_SUPER_PROPERTY_CALL: | 1567 case Call::KEYED_SUPER_PROPERTY_CALL: |
| 1474 EmitKeyedSuperCallWithLoadIC(expr); | 1568 EmitKeyedSuperCallWithLoadIC(expr); |
| 1475 break; | 1569 break; |
| 1476 case Call::SUPER_CALL: | 1570 case Call::SUPER_CALL: |
| 1477 EmitSuperConstructorCall(expr); | 1571 EmitSuperConstructorCall(expr); |
| 1478 break; | 1572 break; |
| 1479 case Call::OTHER_CALL: | 1573 case Call::OTHER_CALL: |
| 1480 // Call to an arbitrary expression not handled specially above. | 1574 // Call to an arbitrary expression not handled specially above. |
| 1481 VisitForStackValue(callee); | 1575 VisitForStackValue(callee); |
| 1576 OperandStackDepthIncrement(1); |
| 1482 __ PushRoot(Heap::kUndefinedValueRootIndex); | 1577 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 1483 // Emit function call. | 1578 // Emit function call. |
| 1484 EmitCall(expr); | 1579 EmitCall(expr); |
| 1485 break; | 1580 break; |
| 1486 } | 1581 } |
| 1487 | 1582 |
| 1488 #ifdef DEBUG | 1583 #ifdef DEBUG |
| 1489 // RecordJSReturnSite should have been called. | 1584 // RecordJSReturnSite should have been called. |
| 1490 DCHECK(expr->return_is_recorded_); | 1585 DCHECK(expr->return_is_recorded_); |
| 1491 #endif | 1586 #endif |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 | 1782 |
| 1688 if (scope == NULL) { | 1783 if (scope == NULL) { |
| 1689 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); | 1784 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); |
| 1690 needs_block_context_ = false; | 1785 needs_block_context_ = false; |
| 1691 } else { | 1786 } else { |
| 1692 needs_block_context_ = scope->NeedsContext(); | 1787 needs_block_context_ = scope->NeedsContext(); |
| 1693 codegen_->scope_ = scope; | 1788 codegen_->scope_ = scope; |
| 1694 { | 1789 { |
| 1695 if (needs_block_context_) { | 1790 if (needs_block_context_) { |
| 1696 Comment cmnt(masm(), "[ Extend block context"); | 1791 Comment cmnt(masm(), "[ Extend block context"); |
| 1697 __ Push(scope->GetScopeInfo(codegen->isolate())); | 1792 codegen_->PushOperand(scope->GetScopeInfo(codegen->isolate())); |
| 1698 codegen_->PushFunctionArgumentForContextAllocation(); | 1793 codegen_->PushFunctionArgumentForContextAllocation(); |
| 1699 __ CallRuntime(Runtime::kPushBlockContext); | 1794 codegen_->CallRuntimeWithOperands(Runtime::kPushBlockContext); |
| 1700 | 1795 |
| 1701 // Replace the context stored in the frame. | 1796 // Replace the context stored in the frame. |
| 1702 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, | 1797 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1703 codegen_->context_register()); | 1798 codegen_->context_register()); |
| 1704 } | 1799 } |
| 1705 CHECK_EQ(0, scope->num_stack_slots()); | 1800 CHECK_EQ(0, scope->num_stack_slots()); |
| 1706 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); | 1801 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); |
| 1707 } | 1802 } |
| 1708 { | 1803 { |
| 1709 Comment cmnt(masm(), "[ Declarations"); | 1804 Comment cmnt(masm(), "[ Declarations"); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1784 return var->mode() == CONST_LEGACY || var->scope()->is_nonlinear() || | 1879 return var->mode() == CONST_LEGACY || var->scope()->is_nonlinear() || |
| 1785 var->initializer_position() >= proxy->position(); | 1880 var->initializer_position() >= proxy->position(); |
| 1786 } | 1881 } |
| 1787 | 1882 |
| 1788 | 1883 |
| 1789 #undef __ | 1884 #undef __ |
| 1790 | 1885 |
| 1791 | 1886 |
| 1792 } // namespace internal | 1887 } // namespace internal |
| 1793 } // namespace v8 | 1888 } // namespace v8 |
| OLD | NEW |