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 |