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 |