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