Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(776)

Side by Side Diff: src/codegen-ia32.cc

Issue 10993: Begin using the virtual frame for assignment statements of the form:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 JumpTarget* false_target, 358 JumpTarget* false_target,
359 bool force_cc) { 359 bool force_cc) {
360 ASSERT(!has_cc()); 360 ASSERT(!has_cc());
361 361
362 { CodeGenState new_state(this, typeof_state, true_target, false_target); 362 { CodeGenState new_state(this, typeof_state, true_target, false_target);
363 Visit(x); 363 Visit(x);
364 } 364 }
365 365
366 if (force_cc && frame_ != NULL && !has_cc()) { 366 if (force_cc && frame_ != NULL && !has_cc()) {
367 // Convert the TOS value to a boolean in the condition code register. 367 // Convert the TOS value to a boolean in the condition code register.
368 frame_->SpillAll();
368 ToBoolean(true_target, false_target); 369 ToBoolean(true_target, false_target);
369 } 370 }
370 371
371 ASSERT(!force_cc || frame_ == NULL || has_cc()); 372 ASSERT(!force_cc || frame_ == NULL || has_cc());
372 } 373 }
373 374
374 375
375 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 376 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
376 JumpTarget true_target(this); 377 JumpTarget true_target(this);
377 JumpTarget false_target(this); 378 JumpTarget false_target(this);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 if (variable != NULL && !variable->is_this() && variable->is_global()) { 442 if (variable != NULL && !variable->is_this() && variable->is_global()) {
442 // NOTE: This is somewhat nasty. We force the compiler to load 443 // NOTE: This is somewhat nasty. We force the compiler to load
443 // the variable as if through '<global>.<variable>' to make sure we 444 // the variable as if through '<global>.<variable>' to make sure we
444 // do not get reference errors. 445 // do not get reference errors.
445 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 446 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
446 Literal key(variable->name()); 447 Literal key(variable->name());
447 // TODO(1241834): Fetch the position from the variable instead of using 448 // TODO(1241834): Fetch the position from the variable instead of using
448 // no position. 449 // no position.
449 Property property(&global, &key, RelocInfo::kNoPosition); 450 Property property(&global, &key, RelocInfo::kNoPosition);
450 Load(&property); 451 Load(&property);
452 frame_->SpillAll();
451 } else { 453 } else {
452 Load(x, INSIDE_TYPEOF); 454 Load(x, INSIDE_TYPEOF);
455 frame_->SpillAll();
453 } 456 }
454 } 457 }
455 458
456 459
457 Reference::Reference(CodeGenerator* cgen, Expression* expression) 460 Reference::Reference(CodeGenerator* cgen, Expression* expression)
458 : cgen_(cgen), expression_(expression), type_(ILLEGAL) { 461 : cgen_(cgen), expression_(expression), type_(ILLEGAL) {
459 cgen->LoadReference(this); 462 cgen->LoadReference(this);
460 } 463 }
461 464
462 465
463 Reference::~Reference() { 466 Reference::~Reference() {
464 cgen_->UnloadReference(this); 467 cgen_->UnloadReference(this);
465 } 468 }
466 469
467 470
468 void CodeGenerator::LoadReference(Reference* ref) { 471 void CodeGenerator::LoadReference(Reference* ref) {
469 Comment cmnt(masm_, "[ LoadReference"); 472 Comment cmnt(masm_, "[ LoadReference");
470 Expression* e = ref->expression(); 473 Expression* e = ref->expression();
471 Property* property = e->AsProperty(); 474 Property* property = e->AsProperty();
472 Variable* var = e->AsVariableProxy()->AsVariable(); 475 Variable* var = e->AsVariableProxy()->AsVariable();
473 476
474 if (property != NULL) { 477 if (property != NULL) {
475 // The expression is either a property or a variable proxy that rewrites 478 // The expression is either a property or a variable proxy that rewrites
476 // to a property. 479 // to a property.
477 Load(property->obj()); 480 Load(property->obj());
481 frame_->SpillAll();
478 // We use a named reference if the key is a literal symbol, unless it is 482 // We use a named reference if the key is a literal symbol, unless it is
479 // a string that can be legally parsed as an integer. This is because 483 // a string that can be legally parsed as an integer. This is because
480 // otherwise we will not get into the slow case code that handles [] on 484 // otherwise we will not get into the slow case code that handles [] on
481 // String objects. 485 // String objects.
482 Literal* literal = property->key()->AsLiteral(); 486 Literal* literal = property->key()->AsLiteral();
483 uint32_t dummy; 487 uint32_t dummy;
484 if (literal != NULL && 488 if (literal != NULL &&
485 literal->handle()->IsSymbol() && 489 literal->handle()->IsSymbol() &&
486 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { 490 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
487 ref->set_type(Reference::NAMED); 491 ref->set_type(Reference::NAMED);
488 } else { 492 } else {
489 Load(property->key()); 493 Load(property->key());
494 frame_->SpillAll();
490 ref->set_type(Reference::KEYED); 495 ref->set_type(Reference::KEYED);
491 } 496 }
492 } else if (var != NULL) { 497 } else if (var != NULL) {
493 // The expression is a variable proxy that does not rewrite to a 498 // The expression is a variable proxy that does not rewrite to a
494 // property. Global variables are treated as named property references. 499 // property. Global variables are treated as named property references.
495 if (var->is_global()) { 500 if (var->is_global()) {
496 LoadGlobal(); 501 LoadGlobal();
497 ref->set_type(Reference::NAMED); 502 ref->set_type(Reference::NAMED);
498 } else { 503 } else {
499 ASSERT(var->slot() != NULL); 504 ASSERT(var->slot() != NULL);
500 ref->set_type(Reference::SLOT); 505 ref->set_type(Reference::SLOT);
501 } 506 }
502 } else { 507 } else {
503 // Anything else is a runtime error. 508 // Anything else is a runtime error.
504 Load(e); 509 Load(e);
510 frame_->SpillAll();
505 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); 511 frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
506 } 512 }
507 } 513 }
508 514
509 515
510 void CodeGenerator::UnloadReference(Reference* ref) { 516 void CodeGenerator::UnloadReference(Reference* ref) {
511 // Pop a reference from the stack while preserving TOS. 517 // Pop a reference from the stack while preserving TOS.
512 Comment cmnt(masm_, "[ UnloadReference"); 518 Comment cmnt(masm_, "[ UnloadReference");
513 int size = ref->size(); 519 int size = ref->size();
514 if (size == 1) { 520 if (size == 1) {
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 1223
1218 1224
1219 // Call the function just below TOS on the stack with the given 1225 // Call the function just below TOS on the stack with the given
1220 // arguments. The receiver is the TOS. 1226 // arguments. The receiver is the TOS.
1221 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1227 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1222 int position) { 1228 int position) {
1223 // Push the arguments ("left-to-right") on the stack. 1229 // Push the arguments ("left-to-right") on the stack.
1224 int arg_count = args->length(); 1230 int arg_count = args->length();
1225 for (int i = 0; i < arg_count; i++) { 1231 for (int i = 0; i < arg_count; i++) {
1226 Load(args->at(i)); 1232 Load(args->at(i));
1233 frame_->SpillAll();
1227 } 1234 }
1228 1235
1229 // Record the position for debugging purposes. 1236 // Record the position for debugging purposes.
1230 __ RecordPosition(position); 1237 __ RecordPosition(position);
1231 1238
1232 // Use the shared code stub to call the function. 1239 // Use the shared code stub to call the function.
1233 CallFunctionStub call_function(arg_count); 1240 CallFunctionStub call_function(arg_count);
1234 frame_->CallStub(&call_function, arg_count + 1); 1241 frame_->CallStub(&call_function, arg_count + 1);
1235 1242
1236 // Restore context and pop function from the stack. 1243 // Restore context and pop function from the stack.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1321 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1315 frame_->EmitPush(Immediate(Smi::FromInt(attr))); 1322 frame_->EmitPush(Immediate(Smi::FromInt(attr)));
1316 // Push initial value, if any. 1323 // Push initial value, if any.
1317 // Note: For variables we must not push an initial value (such as 1324 // Note: For variables we must not push an initial value (such as
1318 // 'undefined') because we may have a (legal) redeclaration and we 1325 // 'undefined') because we may have a (legal) redeclaration and we
1319 // must not destroy the current value. 1326 // must not destroy the current value.
1320 if (node->mode() == Variable::CONST) { 1327 if (node->mode() == Variable::CONST) {
1321 frame_->EmitPush(Immediate(Factory::the_hole_value())); 1328 frame_->EmitPush(Immediate(Factory::the_hole_value()));
1322 } else if (node->fun() != NULL) { 1329 } else if (node->fun() != NULL) {
1323 Load(node->fun()); 1330 Load(node->fun());
1331 frame_->SpillAll();
1324 } else { 1332 } else {
1325 frame_->EmitPush(Immediate(0)); // no initial value! 1333 frame_->EmitPush(Immediate(0)); // no initial value!
1326 } 1334 }
1327 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); 1335 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
1328 // Ignore the return value (declarations are statements). 1336 // Ignore the return value (declarations are statements).
1329 return; 1337 return;
1330 } 1338 }
1331 1339
1332 ASSERT(!var->is_global()); 1340 ASSERT(!var->is_global());
1333 1341
1334 // If we have a function or a constant, we need to initialize the variable. 1342 // If we have a function or a constant, we need to initialize the variable.
1335 Expression* val = NULL; 1343 Expression* val = NULL;
1336 if (node->mode() == Variable::CONST) { 1344 if (node->mode() == Variable::CONST) {
1337 val = new Literal(Factory::the_hole_value()); 1345 val = new Literal(Factory::the_hole_value());
1338 } else { 1346 } else {
1339 val = node->fun(); // NULL if we don't have a function 1347 val = node->fun(); // NULL if we don't have a function
1340 } 1348 }
1341 1349
1342 if (val != NULL) { 1350 if (val != NULL) {
1343 // Set initial value. 1351 // Set initial value.
1344 Reference target(this, node->proxy()); 1352 Reference target(this, node->proxy());
1345 ASSERT(target.is_slot()); 1353 ASSERT(target.is_slot());
1346 Load(val); 1354 Load(val);
1355 frame_->SpillAll();
1347 target.SetValue(NOT_CONST_INIT); 1356 target.SetValue(NOT_CONST_INIT);
1348 // Get rid of the assigned value (declarations are statements). It's 1357 // Get rid of the assigned value (declarations are statements). It's
1349 // safe to pop the value lying on top of the reference before unloading 1358 // safe to pop the value lying on top of the reference before unloading
1350 // the reference itself (which preserves the top of stack) because we 1359 // the reference itself (which preserves the top of stack) because we
1351 // know that it is a zero-sized reference. 1360 // know that it is a zero-sized reference.
1352 frame_->Drop(); 1361 frame_->Drop();
1353 } 1362 }
1354 } 1363 }
1355 1364
1356 1365
1357 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1366 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1358 frame_->SpillAll();
1359 Comment cmnt(masm_, "[ ExpressionStatement"); 1367 Comment cmnt(masm_, "[ ExpressionStatement");
1360 RecordStatementPosition(node); 1368 RecordStatementPosition(node);
1361 Expression* expression = node->expression(); 1369 Expression* expression = node->expression();
1362 expression->MarkAsStatement(); 1370 expression->MarkAsStatement();
1363 Load(expression); 1371 Load(expression);
1364 // Remove the lingering expression result from the top of stack. 1372 // Remove the lingering expression result from the top of stack.
1365 frame_->Drop(); 1373 frame_->Drop();
1374 // Rather than using SpillAll after all recursive calls to Visit over
1375 // statements, we spill here in the only statement type that uses the
1376 // virtual frame. This is temporary.
1377 frame_->SpillAll();
1366 } 1378 }
1367 1379
1368 1380
1369 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1381 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1370 frame_->SpillAll(); 1382 frame_->SpillAll();
1371 Comment cmnt(masm_, "// EmptyStatement"); 1383 Comment cmnt(masm_, "// EmptyStatement");
1372 // nothing to do 1384 // nothing to do
1373 } 1385 }
1374 1386
1375 1387
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1441 if (frame_ != NULL || else_.is_linked()) { 1453 if (frame_ != NULL || else_.is_linked()) {
1442 else_.Bind(); 1454 else_.Bind();
1443 Visit(node->else_statement()); 1455 Visit(node->else_statement());
1444 } 1456 }
1445 1457
1446 } else { 1458 } else {
1447 ASSERT(!has_then_stm && !has_else_stm); 1459 ASSERT(!has_then_stm && !has_else_stm);
1448 // if (cond) 1460 // if (cond)
1449 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1461 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1450 if (frame_ != NULL) { 1462 if (frame_ != NULL) {
1463 frame_->SpillAll();
1451 if (has_cc()) { 1464 if (has_cc()) {
1452 cc_reg_ = no_condition; 1465 cc_reg_ = no_condition;
1453 } else { 1466 } else {
1454 // No cc value set up, that means the boolean was pushed. 1467 // No cc value set up, that means the boolean was pushed.
1455 // Pop it again, since it is not going to be used. 1468 // Pop it again, since it is not going to be used.
1456 frame_->Drop(); 1469 frame_->Drop();
1457 } 1470 }
1458 } 1471 }
1459 } 1472 }
1460 1473
(...skipping 26 matching lines...) Expand all
1487 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1500 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1488 node->target()->break_target()->Jump(); 1501 node->target()->break_target()->Jump();
1489 } 1502 }
1490 1503
1491 1504
1492 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1505 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1493 frame_->SpillAll(); 1506 frame_->SpillAll();
1494 Comment cmnt(masm_, "[ ReturnStatement"); 1507 Comment cmnt(masm_, "[ ReturnStatement");
1495 RecordStatementPosition(node); 1508 RecordStatementPosition(node);
1496 Load(node->expression()); 1509 Load(node->expression());
1510 frame_->SpillAll();
1497 1511
1498 // Move the function result into eax 1512 // Move the function result into eax
1499 frame_->EmitPop(eax); 1513 frame_->EmitPop(eax);
1500 1514
1501 // If we're inside a try statement or the return instruction 1515 // If we're inside a try statement or the return instruction
1502 // sequence has been generated, we just jump to that 1516 // sequence has been generated, we just jump to that
1503 // point. Otherwise, we generate the return instruction sequence and 1517 // point. Otherwise, we generate the return instruction sequence and
1504 // bind the function return label. 1518 // bind the function return label.
1505 if (is_inside_try_ || function_return_.is_bound()) { 1519 if (is_inside_try_ || function_return_.is_bound()) {
1506 function_return_.Jump(); 1520 function_return_.Jump();
(...skipping 20 matching lines...) Expand all
1527 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); 1541 __ SizeOfCodeGeneratedSince(&check_exit_codesize));
1528 } 1542 }
1529 } 1543 }
1530 1544
1531 1545
1532 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1546 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1533 frame_->SpillAll(); 1547 frame_->SpillAll();
1534 Comment cmnt(masm_, "[ WithEnterStatement"); 1548 Comment cmnt(masm_, "[ WithEnterStatement");
1535 RecordStatementPosition(node); 1549 RecordStatementPosition(node);
1536 Load(node->expression()); 1550 Load(node->expression());
1551 frame_->SpillAll();
1537 frame_->CallRuntime(Runtime::kPushContext, 1); 1552 frame_->CallRuntime(Runtime::kPushContext, 1);
1538 1553
1539 if (kDebug) { 1554 if (kDebug) {
1540 JumpTarget verified_true(this); 1555 JumpTarget verified_true(this);
1541 // Verify eax and esi are the same in debug mode 1556 // Verify eax and esi are the same in debug mode
1542 __ cmp(eax, Operand(esi)); 1557 __ cmp(eax, Operand(esi));
1543 verified_true.Branch(equal); 1558 verified_true.Branch(equal);
1544 __ int3(); 1559 __ int3();
1545 verified_true.Bind(); 1560 verified_true.Bind();
1546 } 1561 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1638 1653
1639 1654
1640 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1655 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1641 frame_->SpillAll(); 1656 frame_->SpillAll();
1642 Comment cmnt(masm_, "[ SwitchStatement"); 1657 Comment cmnt(masm_, "[ SwitchStatement");
1643 RecordStatementPosition(node); 1658 RecordStatementPosition(node);
1644 node->set_break_stack_height(break_stack_height_); 1659 node->set_break_stack_height(break_stack_height_);
1645 node->break_target()->set_code_generator(this); 1660 node->break_target()->set_code_generator(this);
1646 1661
1647 Load(node->tag()); 1662 Load(node->tag());
1663 frame_->SpillAll();
1648 1664
1649 if (TryGenerateFastCaseSwitchStatement(node)) { 1665 if (TryGenerateFastCaseSwitchStatement(node)) {
1650 return; 1666 return;
1651 } 1667 }
1652 1668
1653 JumpTarget next_test(this); 1669 JumpTarget next_test(this);
1654 JumpTarget fall_through(this); 1670 JumpTarget fall_through(this);
1655 JumpTarget default_entry(this); 1671 JumpTarget default_entry(this);
1656 JumpTarget default_exit(this); 1672 JumpTarget default_exit(this);
1657 ZoneList<CaseClause*>* cases = node->cases(); 1673 ZoneList<CaseClause*>* cases = node->cases();
1658 int length = cases->length(); 1674 int length = cases->length();
1659 CaseClause* default_clause = NULL; 1675 CaseClause* default_clause = NULL;
1660 1676
1661 for (int i = 0; i < length; i++) { 1677 for (int i = 0; i < length; i++) {
1662 CaseClause* clause = cases->at(i); 1678 CaseClause* clause = cases->at(i);
1663 if (clause->is_default()) { 1679 if (clause->is_default()) {
1664 // Remember the default clause and compile it at the end. 1680 // Remember the default clause and compile it at the end.
1665 default_clause = clause; 1681 default_clause = clause;
1666 continue; 1682 continue;
1667 } 1683 }
1668 1684
1669 Comment cmnt(masm_, "[ Case clause"); 1685 Comment cmnt(masm_, "[ Case clause");
1670 // Compile the test. 1686 // Compile the test.
1671 next_test.Bind(); 1687 next_test.Bind();
1672 next_test.Unuse(); 1688 next_test.Unuse();
1673 // Duplicate TOS. 1689 // Duplicate TOS.
1674 __ mov(eax, frame_->Top()); 1690 __ mov(eax, frame_->Top());
1675 frame_->EmitPush(eax); 1691 frame_->EmitPush(eax);
1676 Load(clause->label()); 1692 Load(clause->label());
1693 frame_->SpillAll();
1677 Comparison(equal, true); 1694 Comparison(equal, true);
1678 Branch(false, &next_test); 1695 Branch(false, &next_test);
1679 1696
1680 // Before entering the body from the test, remove the switch value from 1697 // Before entering the body from the test, remove the switch value from
1681 // the stack. 1698 // the stack.
1682 frame_->Drop(); 1699 frame_->Drop();
1683 1700
1684 // Label the body so that fall through is enabled. 1701 // Label the body so that fall through is enabled.
1685 if (i > 0 && cases->at(i - 1)->is_default()) { 1702 if (i > 0 && cases->at(i - 1)->is_default()) {
1686 default_exit.Bind(); 1703 default_exit.Bind();
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 JumpTarget primitive(this); 1940 JumpTarget primitive(this);
1924 JumpTarget jsobject(this); 1941 JumpTarget jsobject(this);
1925 JumpTarget fixed_array(this); 1942 JumpTarget fixed_array(this);
1926 JumpTarget entry(this); 1943 JumpTarget entry(this);
1927 JumpTarget end_del_check(this); 1944 JumpTarget end_del_check(this);
1928 JumpTarget cleanup(this); 1945 JumpTarget cleanup(this);
1929 JumpTarget exit(this); 1946 JumpTarget exit(this);
1930 1947
1931 // Get the object to enumerate over (converted to JSObject). 1948 // Get the object to enumerate over (converted to JSObject).
1932 Load(node->enumerable()); 1949 Load(node->enumerable());
1950 frame_->SpillAll();
1933 1951
1934 // Both SpiderMonkey and kjs ignore null and undefined in contrast 1952 // Both SpiderMonkey and kjs ignore null and undefined in contrast
1935 // to the specification. 12.6.4 mandates a call to ToObject. 1953 // to the specification. 12.6.4 mandates a call to ToObject.
1936 frame_->EmitPop(eax); 1954 frame_->EmitPop(eax);
1937 1955
1938 // eax: value to be iterated over 1956 // eax: value to be iterated over
1939 __ cmp(eax, Factory::undefined_value()); 1957 __ cmp(eax, Factory::undefined_value());
1940 exit.Branch(equal); 1958 exit.Branch(equal);
1941 __ cmp(eax, Factory::null_value()); 1959 __ cmp(eax, Factory::null_value());
1942 exit.Branch(equal); 1960 exit.Branch(equal);
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
2407 JumpTarget then(this); 2425 JumpTarget then(this);
2408 JumpTarget else_(this); 2426 JumpTarget else_(this);
2409 JumpTarget exit(this); 2427 JumpTarget exit(this);
2410 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 2428 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
2411 if (frame_ != NULL) { 2429 if (frame_ != NULL) {
2412 Branch(false, &else_); 2430 Branch(false, &else_);
2413 } 2431 }
2414 if (frame_ != NULL || then.is_linked()) { 2432 if (frame_ != NULL || then.is_linked()) {
2415 then.Bind(); 2433 then.Bind();
2416 Load(node->then_expression(), typeof_state()); 2434 Load(node->then_expression(), typeof_state());
2435 frame_->SpillAll();
2417 exit.Jump(); 2436 exit.Jump();
2418 } 2437 }
2419 if (else_.is_linked()) { 2438 if (else_.is_linked()) {
2420 else_.Bind(); 2439 else_.Bind();
2421 Load(node->else_expression(), typeof_state()); 2440 Load(node->else_expression(), typeof_state());
2441 frame_->SpillAll();
2422 } 2442 }
2423 exit.Bind(); 2443 exit.Bind();
2424 } 2444 }
2425 2445
2426 2446
2427 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2447 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2428 if (slot->type() == Slot::LOOKUP) { 2448 if (slot->type() == Slot::LOOKUP) {
2429 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2449 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2430 2450
2431 // For now, just do a runtime call. 2451 // For now, just do a runtime call.
(...skipping 23 matching lines...) Expand all
2455 __ mov(eax, Factory::undefined_value()); 2475 __ mov(eax, Factory::undefined_value());
2456 exit.Bind(); 2476 exit.Bind();
2457 frame_->EmitPush(eax); 2477 frame_->EmitPush(eax);
2458 } else { 2478 } else {
2459 frame_->EmitPush(SlotOperand(slot, ecx)); 2479 frame_->EmitPush(SlotOperand(slot, ecx));
2460 } 2480 }
2461 } 2481 }
2462 } 2482 }
2463 2483
2464 2484
2485 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
2486 if (slot->type() == Slot::LOOKUP) {
2487 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2488
2489 // For now, just do a runtime call.
2490 frame_->SpillAll();
2491 frame_->EmitPush(frame_->Context());
2492 frame_->EmitPush(Immediate(slot->var()->name()));
2493
2494 if (init_state == CONST_INIT) {
2495 // Same as the case for a normal store, but ignores attribute
2496 // (e.g. READ_ONLY) of context slot so that we can initialize const
2497 // properties (introduced via eval("const foo = (some expr);")). Also,
2498 // uses the current function context instead of the top context.
2499 //
2500 // Note that we must declare the foo upon entry of eval(), via a
2501 // context slot declaration, but we cannot initialize it at the same
2502 // time, because the const declaration may be at the end of the eval
2503 // code (sigh...) and the const variable may have been used before
2504 // (where its value is 'undefined'). Thus, we can only do the
2505 // initialization when we actually encounter the expression and when
2506 // the expression operands are defined and valid, and thus we need the
2507 // split into 2 operations: declaration of the context slot followed
2508 // by initialization.
2509 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2510 } else {
2511 frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
2512 }
2513 // Storing a variable must keep the (new) value on the expression
2514 // stack. This is necessary for compiling chained assignment
2515 // expressions.
2516 frame_->EmitPush(eax);
2517
2518 } else {
2519 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2520
2521 JumpTarget exit(this);
2522 if (init_state == CONST_INIT) {
2523 ASSERT(slot->var()->mode() == Variable::CONST);
2524 // Only the first const initialization must be executed (the slot
2525 // still contains 'the hole' value). When the assignment is executed,
2526 // the code is identical to a normal store (see below).
2527 Comment cmnt(masm_, "[ Init const");
2528 frame_->SpillAll();
2529 __ mov(eax, SlotOperand(slot, ecx));
2530 __ cmp(eax, Factory::the_hole_value());
2531 exit.Branch(not_equal);
2532 }
2533
2534 // We must execute the store. Storing a variable must keep the (new)
2535 // value on the stack. This is necessary for compiling assignment
2536 // expressions.
2537 //
2538 // Note: We will reach here even with slot->var()->mode() ==
2539 // Variable::CONST because of const declarations which will initialize
2540 // consts to 'the hole' value and by doing so, end up calling this code.
2541 if (slot->type() == Slot::PARAMETER) {
2542 frame_->StoreToParameterAt(slot->index());
2543 } else if (slot->type() == Slot::LOCAL) {
2544 frame_->StoreToLocalAt(slot->index());
2545 } else {
2546 // The other slot types (LOOKUP and GLOBAL) cannot reach here.
2547 ASSERT(slot->type() == Slot::CONTEXT);
2548 frame_->SpillAll();
2549 frame_->EmitPop(eax);
2550 __ mov(SlotOperand(slot, ecx), eax);
2551 frame_->EmitPush(eax); // RecordWrite may destroy the value in eax.
2552 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
2553 __ RecordWrite(ecx, offset, eax, ebx);
2554 }
2555
2556 // If we definitely did not jump over the assignment, we do not need
2557 // to bind the exit label. Doing so can defeat peephole
2558 // optimization.
2559 if (init_state == CONST_INIT) {
2560 exit.Bind();
2561 }
2562 }
2563 }
2564
2565
2465 void CodeGenerator::VisitSlot(Slot* node) { 2566 void CodeGenerator::VisitSlot(Slot* node) {
2466 frame_->SpillAll(); 2567 frame_->SpillAll();
2467 Comment cmnt(masm_, "[ Slot"); 2568 Comment cmnt(masm_, "[ Slot");
2468 LoadFromSlot(node, typeof_state()); 2569 LoadFromSlot(node, typeof_state());
2469 } 2570 }
2470 2571
2471 2572
2472 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2573 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2473 frame_->SpillAll(); 2574 frame_->SpillAll();
2474 Comment cmnt(masm_, "[ VariableProxy"); 2575 Comment cmnt(masm_, "[ VariableProxy");
(...skipping 11 matching lines...) Expand all
2486 ASSERT(frame_ != NULL); 2587 ASSERT(frame_ != NULL);
2487 } else { 2588 } else {
2488 ASSERT(var->is_global()); 2589 ASSERT(var->is_global());
2489 Reference ref(this, node); 2590 Reference ref(this, node);
2490 ref.GetValue(typeof_state()); 2591 ref.GetValue(typeof_state());
2491 } 2592 }
2492 } 2593 }
2493 2594
2494 2595
2495 void CodeGenerator::VisitLiteral(Literal* node) { 2596 void CodeGenerator::VisitLiteral(Literal* node) {
2496 frame_->SpillAll();
2497 Comment cmnt(masm_, "[ Literal"); 2597 Comment cmnt(masm_, "[ Literal");
2498 if (node->handle()->IsSmi() && !IsInlineSmi(node)) { 2598 if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
2499 // To prevent long attacker-controlled byte sequences in code, larger 2599 // To prevent long attacker-controlled byte sequences in code, larger
2500 // Smis are loaded in two steps. 2600 // Smis are loaded in two steps via a temporary register.
William Hesse 2008/11/28 10:32:45 Is now the time for special-casing small literals,
Kevin Millikin (Chromium) 2008/11/28 12:19:08 It's only the non-"InlineSmi" literals that are lo
2601 Register temp = allocator_->Allocate();
2501 int bits = reinterpret_cast<int>(*node->handle()); 2602 int bits = reinterpret_cast<int>(*node->handle());
2502 __ mov(eax, bits & 0x0000FFFF); 2603 ASSERT(!temp.is(no_reg));
2503 __ xor_(eax, bits & 0xFFFF0000); 2604 __ mov(temp, bits & 0x0000FFFF);
2504 frame_->EmitPush(eax); 2605 __ xor_(temp, bits & 0xFFFF0000);
2606 frame_->Push(temp);
2607 allocator_->Unuse(temp);
2505 } else { 2608 } else {
2506 frame_->EmitPush(Immediate(node->handle())); 2609 frame_->Push(node->handle());
2507 } 2610 }
2508 } 2611 }
2509 2612
2510 2613
2511 class RegExpDeferred: public DeferredCode { 2614 class RegExpDeferred: public DeferredCode {
2512 public: 2615 public:
2513 RegExpDeferred(CodeGenerator* generator, RegExpLiteral* node) 2616 RegExpDeferred(CodeGenerator* generator, RegExpLiteral* node)
2514 : DeferredCode(generator), node_(node) { 2617 : DeferredCode(generator), node_(node) {
2515 set_comment("[ RegExpDeferred"); 2618 set_comment("[ RegExpDeferred");
2516 } 2619 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2634 ObjectLiteral::Property* property = node->properties()->at(i); 2737 ObjectLiteral::Property* property = node->properties()->at(i);
2635 switch (property->kind()) { 2738 switch (property->kind()) {
2636 case ObjectLiteral::Property::CONSTANT: break; 2739 case ObjectLiteral::Property::CONSTANT: break;
2637 case ObjectLiteral::Property::COMPUTED: { 2740 case ObjectLiteral::Property::COMPUTED: {
2638 Handle<Object> key(property->key()->handle()); 2741 Handle<Object> key(property->key()->handle());
2639 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2742 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2640 if (key->IsSymbol()) { 2743 if (key->IsSymbol()) {
2641 __ mov(eax, frame_->Top()); 2744 __ mov(eax, frame_->Top());
2642 frame_->EmitPush(eax); 2745 frame_->EmitPush(eax);
2643 Load(property->value()); 2746 Load(property->value());
2747 frame_->SpillAll();
2644 frame_->EmitPop(eax); 2748 frame_->EmitPop(eax);
2645 __ Set(ecx, Immediate(key)); 2749 __ Set(ecx, Immediate(key));
2646 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 2750 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
2647 frame_->Drop(); 2751 frame_->Drop();
2648 // Ignore result. 2752 // Ignore result.
2649 break; 2753 break;
2650 } 2754 }
2651 // Fall through 2755 // Fall through
2652 } 2756 }
2653 case ObjectLiteral::Property::PROTOTYPE: { 2757 case ObjectLiteral::Property::PROTOTYPE: {
2654 __ mov(eax, frame_->Top()); 2758 __ mov(eax, frame_->Top());
2655 frame_->EmitPush(eax); 2759 frame_->EmitPush(eax);
2656 Load(property->key()); 2760 Load(property->key());
2761 frame_->SpillAll();
2657 Load(property->value()); 2762 Load(property->value());
2763 frame_->SpillAll();
2658 frame_->CallRuntime(Runtime::kSetProperty, 3); 2764 frame_->CallRuntime(Runtime::kSetProperty, 3);
2659 // Ignore result. 2765 // Ignore result.
2660 break; 2766 break;
2661 } 2767 }
2662 case ObjectLiteral::Property::SETTER: { 2768 case ObjectLiteral::Property::SETTER: {
2663 // Duplicate the resulting object on the stack. The runtime 2769 // Duplicate the resulting object on the stack. The runtime
2664 // function will pop the three arguments passed in. 2770 // function will pop the three arguments passed in.
2665 __ mov(eax, frame_->Top()); 2771 __ mov(eax, frame_->Top());
2666 frame_->EmitPush(eax); 2772 frame_->EmitPush(eax);
2667 Load(property->key()); 2773 Load(property->key());
2774 frame_->SpillAll();
2668 frame_->EmitPush(Immediate(Smi::FromInt(1))); 2775 frame_->EmitPush(Immediate(Smi::FromInt(1)));
2669 Load(property->value()); 2776 Load(property->value());
2777 frame_->SpillAll();
2670 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2778 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2671 // Ignore result. 2779 // Ignore result.
2672 break; 2780 break;
2673 } 2781 }
2674 case ObjectLiteral::Property::GETTER: { 2782 case ObjectLiteral::Property::GETTER: {
2675 // Duplicate the resulting object on the stack. The runtime 2783 // Duplicate the resulting object on the stack. The runtime
2676 // function will pop the three arguments passed in. 2784 // function will pop the three arguments passed in.
2677 __ mov(eax, frame_->Top()); 2785 __ mov(eax, frame_->Top());
2678 frame_->EmitPush(eax); 2786 frame_->EmitPush(eax);
2679 Load(property->key()); 2787 Load(property->key());
2788 frame_->SpillAll();
2680 frame_->EmitPush(Immediate(Smi::FromInt(0))); 2789 frame_->EmitPush(Immediate(Smi::FromInt(0)));
2681 Load(property->value()); 2790 Load(property->value());
2791 frame_->SpillAll();
2682 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2792 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2683 // Ignore result. 2793 // Ignore result.
2684 break; 2794 break;
2685 } 2795 }
2686 default: UNREACHABLE(); 2796 default: UNREACHABLE();
2687 } 2797 }
2688 } 2798 }
2689 } 2799 }
2690 2800
2691 2801
(...skipping 16 matching lines...) Expand all
2708 // Generate code to set the elements in the array that are not 2818 // Generate code to set the elements in the array that are not
2709 // literals. 2819 // literals.
2710 for (int i = 0; i < node->values()->length(); i++) { 2820 for (int i = 0; i < node->values()->length(); i++) {
2711 Expression* value = node->values()->at(i); 2821 Expression* value = node->values()->at(i);
2712 2822
2713 // If value is literal the property value is already 2823 // If value is literal the property value is already
2714 // set in the boilerplate object. 2824 // set in the boilerplate object.
2715 if (value->AsLiteral() == NULL) { 2825 if (value->AsLiteral() == NULL) {
2716 // The property must be set by generated code. 2826 // The property must be set by generated code.
2717 Load(value); 2827 Load(value);
2828 frame_->SpillAll();
2718 2829
2719 // Get the value off the stack. 2830 // Get the value off the stack.
2720 frame_->EmitPop(eax); 2831 frame_->EmitPop(eax);
2721 // Fetch the object literal while leaving on the stack. 2832 // Fetch the object literal while leaving on the stack.
2722 __ mov(ecx, frame_->Top()); 2833 __ mov(ecx, frame_->Top());
2723 // Get the elements array. 2834 // Get the elements array.
2724 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); 2835 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
2725 2836
2726 // Write to the indexed properties array. 2837 // Write to the indexed properties array.
2727 int offset = i * kPointerSize + Array::kHeaderSize; 2838 int offset = i * kPointerSize + Array::kHeaderSize;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2760 Load(node->value()); 2871 Load(node->value());
2761 2872
2762 } else { 2873 } else {
2763 target.GetValue(NOT_INSIDE_TYPEOF); 2874 target.GetValue(NOT_INSIDE_TYPEOF);
2764 Literal* literal = node->value()->AsLiteral(); 2875 Literal* literal = node->value()->AsLiteral();
2765 if (IsInlineSmi(literal)) { 2876 if (IsInlineSmi(literal)) {
2766 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, 2877 SmiOperation(node->binary_op(), node->type(), literal->handle(), false,
2767 NO_OVERWRITE); 2878 NO_OVERWRITE);
2768 } else { 2879 } else {
2769 Load(node->value()); 2880 Load(node->value());
2881 frame_->SpillAll();
2770 GenericBinaryOperation(node->binary_op(), node->type()); 2882 GenericBinaryOperation(node->binary_op(), node->type());
2771 } 2883 }
2772 } 2884 }
2773 2885
2774 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 2886 Variable* var = node->target()->AsVariableProxy()->AsVariable();
2775 if (var != NULL && 2887 if (var != NULL &&
2776 var->mode() == Variable::CONST && 2888 var->mode() == Variable::CONST &&
2777 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 2889 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
2778 // Assignment ignored - leave the value on the stack. 2890 // Assignment ignored - leave the value on the stack.
2779 } else { 2891 } else {
2780 __ RecordPosition(node->position()); 2892 __ RecordPosition(node->position());
2781 if (node->op() == Token::INIT_CONST) { 2893 if (node->op() == Token::INIT_CONST) {
2782 // Dynamic constant initializations must use the function context 2894 // Dynamic constant initializations must use the function context
2783 // and initialize the actual constant declared. Dynamic variable 2895 // and initialize the actual constant declared. Dynamic variable
2784 // initializations are simply assignments and use SetValue. 2896 // initializations are simply assignments and use SetValue.
2785 target.SetValue(CONST_INIT); 2897 target.SetValue(CONST_INIT);
2786 } else { 2898 } else {
2787 target.SetValue(NOT_CONST_INIT); 2899 target.SetValue(NOT_CONST_INIT);
2788 } 2900 }
2789 } 2901 }
2790 } 2902 }
2791 } 2903 }
2792 2904
2793 2905
2794 void CodeGenerator::VisitThrow(Throw* node) { 2906 void CodeGenerator::VisitThrow(Throw* node) {
2795 frame_->SpillAll(); 2907 frame_->SpillAll();
2796 Comment cmnt(masm_, "[ Throw"); 2908 Comment cmnt(masm_, "[ Throw");
2797 2909
2798 Load(node->exception()); 2910 Load(node->exception());
2911 frame_->SpillAll();
2799 __ RecordPosition(node->position()); 2912 __ RecordPosition(node->position());
2800 frame_->CallRuntime(Runtime::kThrow, 1); 2913 frame_->CallRuntime(Runtime::kThrow, 1);
2801 frame_->EmitPush(eax); 2914 frame_->EmitPush(eax);
2802 } 2915 }
2803 2916
2804 2917
2805 void CodeGenerator::VisitProperty(Property* node) { 2918 void CodeGenerator::VisitProperty(Property* node) {
2806 frame_->SpillAll(); 2919 frame_->SpillAll();
2807 Comment cmnt(masm_, "[ Property"); 2920 Comment cmnt(masm_, "[ Property");
2808 Reference property(this, node); 2921 Reference property(this, node);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2841 frame_->EmitPush(Immediate(var->name())); 2954 frame_->EmitPush(Immediate(var->name()));
2842 2955
2843 // Pass the global object as the receiver and let the IC stub 2956 // Pass the global object as the receiver and let the IC stub
2844 // patch the stack to use the global proxy as 'this' in the 2957 // patch the stack to use the global proxy as 'this' in the
2845 // invoked function. 2958 // invoked function.
2846 LoadGlobal(); 2959 LoadGlobal();
2847 // Load the arguments. 2960 // Load the arguments.
2848 int arg_count = args->length(); 2961 int arg_count = args->length();
2849 for (int i = 0; i < arg_count; i++) { 2962 for (int i = 0; i < arg_count; i++) {
2850 Load(args->at(i)); 2963 Load(args->at(i));
2964 frame_->SpillAll();
2851 } 2965 }
2852 2966
2853 // Setup the receiver register and call the IC initialization code. 2967 // Setup the receiver register and call the IC initialization code.
2854 Handle<Code> stub = (loop_nesting() > 0) 2968 Handle<Code> stub = (loop_nesting() > 0)
2855 ? ComputeCallInitializeInLoop(arg_count) 2969 ? ComputeCallInitializeInLoop(arg_count)
2856 : ComputeCallInitialize(arg_count); 2970 : ComputeCallInitialize(arg_count);
2857 __ RecordPosition(node->position()); 2971 __ RecordPosition(node->position());
2858 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, 2972 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
2859 arg_count + 1); 2973 arg_count + 1);
2860 __ mov(esi, frame_->Context()); 2974 __ mov(esi, frame_->Context());
(...skipping 25 matching lines...) Expand all
2886 Literal* literal = property->key()->AsLiteral(); 3000 Literal* literal = property->key()->AsLiteral();
2887 3001
2888 if (literal != NULL && literal->handle()->IsSymbol()) { 3002 if (literal != NULL && literal->handle()->IsSymbol()) {
2889 // ------------------------------------------------------------------ 3003 // ------------------------------------------------------------------
2890 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 3004 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2891 // ------------------------------------------------------------------ 3005 // ------------------------------------------------------------------
2892 3006
2893 // Push the name of the function and the receiver onto the stack. 3007 // Push the name of the function and the receiver onto the stack.
2894 frame_->EmitPush(Immediate(literal->handle())); 3008 frame_->EmitPush(Immediate(literal->handle()));
2895 Load(property->obj()); 3009 Load(property->obj());
3010 frame_->SpillAll();
2896 3011
2897 // Load the arguments. 3012 // Load the arguments.
2898 int arg_count = args->length(); 3013 int arg_count = args->length();
2899 for (int i = 0; i < arg_count; i++) { 3014 for (int i = 0; i < arg_count; i++) {
2900 Load(args->at(i)); 3015 Load(args->at(i));
3016 frame_->SpillAll();
2901 } 3017 }
2902 3018
2903 // Call the IC initialization code. 3019 // Call the IC initialization code.
2904 Handle<Code> stub = (loop_nesting() > 0) 3020 Handle<Code> stub = (loop_nesting() > 0)
2905 ? ComputeCallInitializeInLoop(arg_count) 3021 ? ComputeCallInitializeInLoop(arg_count)
2906 : ComputeCallInitialize(arg_count); 3022 : ComputeCallInitialize(arg_count);
2907 __ RecordPosition(node->position()); 3023 __ RecordPosition(node->position());
2908 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 3024 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
2909 __ mov(esi, frame_->Context()); 3025 __ mov(esi, frame_->Context());
2910 3026
(...skipping 17 matching lines...) Expand all
2928 CallWithArguments(args, node->position()); 3044 CallWithArguments(args, node->position());
2929 } 3045 }
2930 3046
2931 } else { 3047 } else {
2932 // ---------------------------------- 3048 // ----------------------------------
2933 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 3049 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2934 // ---------------------------------- 3050 // ----------------------------------
2935 3051
2936 // Load the function. 3052 // Load the function.
2937 Load(function); 3053 Load(function);
3054 frame_->SpillAll();
2938 3055
2939 // Pass the global proxy as the receiver. 3056 // Pass the global proxy as the receiver.
2940 LoadGlobalReceiver(eax); 3057 LoadGlobalReceiver(eax);
2941 3058
2942 // Call the function. 3059 // Call the function.
2943 CallWithArguments(args, node->position()); 3060 CallWithArguments(args, node->position());
2944 } 3061 }
2945 } 3062 }
2946 3063
2947 3064
2948 void CodeGenerator::VisitCallNew(CallNew* node) { 3065 void CodeGenerator::VisitCallNew(CallNew* node) {
2949 frame_->SpillAll(); 3066 frame_->SpillAll();
2950 Comment cmnt(masm_, "[ CallNew"); 3067 Comment cmnt(masm_, "[ CallNew");
2951 3068
2952 // According to ECMA-262, section 11.2.2, page 44, the function 3069 // According to ECMA-262, section 11.2.2, page 44, the function
2953 // expression in new calls must be evaluated before the 3070 // expression in new calls must be evaluated before the
2954 // arguments. This is different from ordinary calls, where the 3071 // arguments. This is different from ordinary calls, where the
2955 // actual function to call is resolved after the arguments have been 3072 // actual function to call is resolved after the arguments have been
2956 // evaluated. 3073 // evaluated.
2957 3074
2958 // Compute function to call and use the global object as the 3075 // Compute function to call and use the global object as the
2959 // receiver. There is no need to use the global proxy here because 3076 // receiver. There is no need to use the global proxy here because
2960 // it will always be replaced with a newly allocated object. 3077 // it will always be replaced with a newly allocated object.
2961 Load(node->expression()); 3078 Load(node->expression());
3079 frame_->SpillAll();
2962 LoadGlobal(); 3080 LoadGlobal();
2963 3081
2964 // Push the arguments ("left-to-right") on the stack. 3082 // Push the arguments ("left-to-right") on the stack.
2965 ZoneList<Expression*>* args = node->arguments(); 3083 ZoneList<Expression*>* args = node->arguments();
2966 int arg_count = args->length(); 3084 int arg_count = args->length();
2967 for (int i = 0; i < arg_count; i++) { 3085 for (int i = 0; i < arg_count; i++) {
2968 Load(args->at(i)); 3086 Load(args->at(i));
3087 frame_->SpillAll();
2969 } 3088 }
2970 3089
2971 // Constructors are called with the number of arguments in register 3090 // Constructors are called with the number of arguments in register
2972 // eax for now. Another option would be to have separate construct 3091 // eax for now. Another option would be to have separate construct
2973 // call trampolines per different arguments counts encountered. 3092 // call trampolines per different arguments counts encountered.
2974 __ Set(eax, Immediate(arg_count)); 3093 __ Set(eax, Immediate(arg_count));
2975 3094
2976 // Load the function into temporary function slot as per calling 3095 // Load the function into temporary function slot as per calling
2977 // convention. 3096 // convention.
2978 __ mov(edi, frame_->ElementAt(arg_count + 1)); 3097 __ mov(edi, frame_->ElementAt(arg_count + 1));
2979 3098
2980 // Call the construct call builtin that handles allocation and 3099 // Call the construct call builtin that handles allocation and
2981 // constructor invocation. 3100 // constructor invocation.
2982 __ RecordPosition(node->position()); 3101 __ RecordPosition(node->position());
2983 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 3102 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
2984 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1); 3103 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
2985 // Discard the function and "push" the newly created object. 3104 // Discard the function and "push" the newly created object.
2986 __ mov(frame_->Top(), eax); 3105 __ mov(frame_->Top(), eax);
2987 } 3106 }
2988 3107
2989 3108
2990 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 3109 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
2991 ASSERT(args->length() == 1); 3110 ASSERT(args->length() == 1);
2992 Load(args->at(0)); 3111 Load(args->at(0));
3112 frame_->SpillAll();
iposva 2008/12/03 07:04:40 Is there a single call to Load in this file that i
Kevin Millikin (Chromium) 2008/12/03 15:08:38 Actually there are two (but they are easy to miss)
2993 frame_->EmitPop(eax); 3113 frame_->EmitPop(eax);
2994 __ test(eax, Immediate(kSmiTagMask)); 3114 __ test(eax, Immediate(kSmiTagMask));
2995 cc_reg_ = zero; 3115 cc_reg_ = zero;
2996 } 3116 }
2997 3117
2998 3118
2999 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3119 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3000 ASSERT(args->length() == 1); 3120 ASSERT(args->length() == 1);
3001 Load(args->at(0)); 3121 Load(args->at(0));
3122 frame_->SpillAll();
3002 frame_->EmitPop(eax); 3123 frame_->EmitPop(eax);
3003 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 3124 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
3004 cc_reg_ = zero; 3125 cc_reg_ = zero;
3005 } 3126 }
3006 3127
3007 3128
3008 // This generates code that performs a charCodeAt() call or returns 3129 // This generates code that performs a charCodeAt() call or returns
3009 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3130 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3010 // It can handle flat and sliced strings, 8 and 16 bit characters and 3131 // It can handle flat and sliced strings, 8 and 16 bit characters and
3011 // cons strings where the answer is found in the left hand branch of the 3132 // cons strings where the answer is found in the left hand branch of the
3012 // cons. The slow case will flatten the string, which will ensure that 3133 // cons. The slow case will flatten the string, which will ensure that
3013 // the answer is in the left hand side the next time around. 3134 // the answer is in the left hand side the next time around.
3014 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3135 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3015 ASSERT(args->length() == 2); 3136 ASSERT(args->length() == 2);
3016 3137
3017 JumpTarget slow_case(this); 3138 JumpTarget slow_case(this);
3018 JumpTarget end(this); 3139 JumpTarget end(this);
3019 JumpTarget not_a_flat_string(this); 3140 JumpTarget not_a_flat_string(this);
3020 JumpTarget not_a_cons_string_either(this); 3141 JumpTarget not_a_cons_string_either(this);
3021 JumpTarget try_again_with_new_string(this); 3142 JumpTarget try_again_with_new_string(this);
3022 JumpTarget ascii_string(this); 3143 JumpTarget ascii_string(this);
3023 JumpTarget got_char_code(this); 3144 JumpTarget got_char_code(this);
3024 3145
3025 // Load the string into eax. 3146 // Load the string into eax.
3026 Load(args->at(0)); 3147 Load(args->at(0));
3148 frame_->SpillAll();
3027 frame_->EmitPop(eax); 3149 frame_->EmitPop(eax);
3028 // If the receiver is a smi return undefined. 3150 // If the receiver is a smi return undefined.
3029 ASSERT(kSmiTag == 0); 3151 ASSERT(kSmiTag == 0);
3030 __ test(eax, Immediate(kSmiTagMask)); 3152 __ test(eax, Immediate(kSmiTagMask));
3031 slow_case.Branch(zero, not_taken); 3153 slow_case.Branch(zero, not_taken);
3032 3154
3033 // Load the index into ebx. 3155 // Load the index into ebx.
3034 Load(args->at(1)); 3156 Load(args->at(1));
3157 frame_->SpillAll();
3035 frame_->EmitPop(ebx); 3158 frame_->EmitPop(ebx);
3036 3159
3037 // Check for negative or non-smi index. 3160 // Check for negative or non-smi index.
3038 ASSERT(kSmiTag == 0); 3161 ASSERT(kSmiTag == 0);
3039 __ test(ebx, Immediate(kSmiTagMask | 0x80000000)); 3162 __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
3040 slow_case.Branch(not_zero, not_taken); 3163 slow_case.Branch(not_zero, not_taken);
3041 // Get rid of the smi tag on the index. 3164 // Get rid of the smi tag on the index.
3042 __ sar(ebx, kSmiTagSize); 3165 __ sar(ebx, kSmiTagSize);
3043 3166
3044 try_again_with_new_string.Bind(); 3167 try_again_with_new_string.Bind();
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
3120 slow_case.Bind(); 3243 slow_case.Bind();
3121 frame_->EmitPush(Immediate(Factory::undefined_value())); 3244 frame_->EmitPush(Immediate(Factory::undefined_value()));
3122 3245
3123 end.Bind(); 3246 end.Bind();
3124 } 3247 }
3125 3248
3126 3249
3127 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3250 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3128 ASSERT(args->length() == 1); 3251 ASSERT(args->length() == 1);
3129 Load(args->at(0)); 3252 Load(args->at(0));
3253 frame_->SpillAll();
3130 JumpTarget answer(this); 3254 JumpTarget answer(this);
3131 // We need the CC bits to come out as not_equal in the case where the 3255 // We need the CC bits to come out as not_equal in the case where the
3132 // object is a smi. This can't be done with the usual test opcode so 3256 // object is a smi. This can't be done with the usual test opcode so
3133 // we copy the object to ecx and do some destructive ops on it that 3257 // we copy the object to ecx and do some destructive ops on it that
3134 // result in the right CC bits. 3258 // result in the right CC bits.
3135 frame_->EmitPop(eax); 3259 frame_->EmitPop(eax);
3136 __ mov(ecx, Operand(eax)); 3260 __ mov(ecx, Operand(eax));
3137 __ and_(ecx, kSmiTagMask); 3261 __ and_(ecx, kSmiTagMask);
3138 __ xor_(ecx, kSmiTagMask); 3262 __ xor_(ecx, kSmiTagMask);
3139 answer.Branch(not_equal, not_taken); 3263 answer.Branch(not_equal, not_taken);
(...skipping 19 matching lines...) Expand all
3159 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 3283 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
3160 frame_->CallStub(&stub, 0); 3284 frame_->CallStub(&stub, 0);
3161 frame_->EmitPush(eax); 3285 frame_->EmitPush(eax);
3162 } 3286 }
3163 3287
3164 3288
3165 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3289 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3166 ASSERT(args->length() == 1); 3290 ASSERT(args->length() == 1);
3167 JumpTarget leave(this); 3291 JumpTarget leave(this);
3168 Load(args->at(0)); // Load the object. 3292 Load(args->at(0)); // Load the object.
3293 frame_->SpillAll();
3169 __ mov(eax, frame_->Top()); 3294 __ mov(eax, frame_->Top());
3170 // if (object->IsSmi()) return object. 3295 // if (object->IsSmi()) return object.
3171 __ test(eax, Immediate(kSmiTagMask)); 3296 __ test(eax, Immediate(kSmiTagMask));
3172 leave.Branch(zero, taken); 3297 leave.Branch(zero, taken);
3173 // It is a heap object - get map. 3298 // It is a heap object - get map.
3174 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 3299 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3175 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 3300 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3176 // if (!object->IsJSValue()) return object. 3301 // if (!object->IsJSValue()) return object.
3177 __ cmp(ecx, JS_VALUE_TYPE); 3302 __ cmp(ecx, JS_VALUE_TYPE);
3178 leave.Branch(not_equal, not_taken); 3303 leave.Branch(not_equal, not_taken);
3179 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 3304 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
3180 __ mov(frame_->Top(), eax); 3305 __ mov(frame_->Top(), eax);
3181 leave.Bind(); 3306 leave.Bind();
3182 } 3307 }
3183 3308
3184 3309
3185 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 3310 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
3186 ASSERT(args->length() == 2); 3311 ASSERT(args->length() == 2);
3187 JumpTarget leave(this); 3312 JumpTarget leave(this);
3188 Load(args->at(0)); // Load the object. 3313 Load(args->at(0)); // Load the object.
3314 frame_->SpillAll();
3189 Load(args->at(1)); // Load the value. 3315 Load(args->at(1)); // Load the value.
3316 frame_->SpillAll();
3190 __ mov(eax, frame_->ElementAt(1)); 3317 __ mov(eax, frame_->ElementAt(1));
3191 __ mov(ecx, frame_->Top()); 3318 __ mov(ecx, frame_->Top());
3192 // if (object->IsSmi()) return object. 3319 // if (object->IsSmi()) return object.
3193 __ test(eax, Immediate(kSmiTagMask)); 3320 __ test(eax, Immediate(kSmiTagMask));
3194 leave.Branch(zero, taken); 3321 leave.Branch(zero, taken);
3195 // It is a heap object - get map. 3322 // It is a heap object - get map.
3196 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 3323 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3197 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 3324 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
3198 // if (!object->IsJSValue()) return object. 3325 // if (!object->IsJSValue()) return object.
3199 __ cmp(ebx, JS_VALUE_TYPE); 3326 __ cmp(ebx, JS_VALUE_TYPE);
3200 leave.Branch(not_equal, not_taken); 3327 leave.Branch(not_equal, not_taken);
3201 // Store the value. 3328 // Store the value.
3202 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx); 3329 __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx);
3203 // Update the write barrier. 3330 // Update the write barrier.
3204 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx); 3331 __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx);
3205 // Leave. 3332 // Leave.
3206 leave.Bind(); 3333 leave.Bind();
3207 __ mov(ecx, frame_->Top()); 3334 __ mov(ecx, frame_->Top());
3208 frame_->Drop(); 3335 frame_->Drop();
3209 __ mov(frame_->Top(), ecx); 3336 __ mov(frame_->Top(), ecx);
3210 } 3337 }
3211 3338
3212 3339
3213 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 3340 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
3214 ASSERT(args->length() == 1); 3341 ASSERT(args->length() == 1);
3215 3342
3216 // Load the key onto the stack and set register eax to the formal 3343 // Load the key onto the stack and set register eax to the formal
3217 // parameters count for the currently executing function. 3344 // parameters count for the currently executing function.
3218 Load(args->at(0)); 3345 Load(args->at(0));
3346 frame_->SpillAll();
3219 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 3347 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
3220 3348
3221 // Call the shared stub to get to arguments[key]. 3349 // Call the shared stub to get to arguments[key].
3222 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 3350 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
3223 frame_->CallStub(&stub, 0); 3351 frame_->CallStub(&stub, 0);
3224 __ mov(frame_->Top(), eax); 3352 __ mov(frame_->Top(), eax);
3225 } 3353 }
3226 3354
3227 3355
3228 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 3356 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
3229 ASSERT(args->length() == 2); 3357 ASSERT(args->length() == 2);
3230 3358
3231 // Load the two objects into registers and perform the comparison. 3359 // Load the two objects into registers and perform the comparison.
3232 Load(args->at(0)); 3360 Load(args->at(0));
3361 frame_->SpillAll();
3233 Load(args->at(1)); 3362 Load(args->at(1));
3363 frame_->SpillAll();
3234 frame_->EmitPop(eax); 3364 frame_->EmitPop(eax);
3235 frame_->EmitPop(ecx); 3365 frame_->EmitPop(ecx);
3236 __ cmp(eax, Operand(ecx)); 3366 __ cmp(eax, Operand(ecx));
3237 cc_reg_ = equal; 3367 cc_reg_ = equal;
3238 } 3368 }
3239 3369
3240 3370
3241 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 3371 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
3242 frame_->SpillAll(); 3372 frame_->SpillAll();
3243 if (CheckForInlineRuntimeCall(node)) { 3373 if (CheckForInlineRuntimeCall(node)) {
3244 return; 3374 return;
3245 } 3375 }
3246 3376
3247 ZoneList<Expression*>* args = node->arguments(); 3377 ZoneList<Expression*>* args = node->arguments();
3248 Comment cmnt(masm_, "[ CallRuntime"); 3378 Comment cmnt(masm_, "[ CallRuntime");
3249 Runtime::Function* function = node->function(); 3379 Runtime::Function* function = node->function();
3250 3380
3251 if (function == NULL) { 3381 if (function == NULL) {
3252 // Prepare stack for calling JS runtime function. 3382 // Prepare stack for calling JS runtime function.
3253 frame_->EmitPush(Immediate(node->name())); 3383 frame_->EmitPush(Immediate(node->name()));
3254 // Push the builtins object found in the current global object. 3384 // Push the builtins object found in the current global object.
3255 __ mov(edx, GlobalObject()); 3385 __ mov(edx, GlobalObject());
3256 frame_->EmitPush(FieldOperand(edx, GlobalObject::kBuiltinsOffset)); 3386 frame_->EmitPush(FieldOperand(edx, GlobalObject::kBuiltinsOffset));
3257 } 3387 }
3258 3388
3259 // Push the arguments ("left-to-right"). 3389 // Push the arguments ("left-to-right").
3260 int arg_count = args->length(); 3390 int arg_count = args->length();
3261 for (int i = 0; i < arg_count; i++) { 3391 for (int i = 0; i < arg_count; i++) {
3262 Load(args->at(i)); 3392 Load(args->at(i));
3393 frame_->SpillAll();
3263 } 3394 }
3264 3395
3265 if (function == NULL) { 3396 if (function == NULL) {
3266 // Call the JS runtime function. 3397 // Call the JS runtime function.
3267 Handle<Code> stub = ComputeCallInitialize(arg_count); 3398 Handle<Code> stub = ComputeCallInitialize(arg_count);
3268 __ Set(eax, Immediate(args->length())); 3399 __ Set(eax, Immediate(args->length()));
3269 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 3400 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
3270 __ mov(esi, frame_->Context()); 3401 __ mov(esi, frame_->Context());
3271 __ mov(frame_->Top(), eax); 3402 __ mov(frame_->Top(), eax);
3272 } else { 3403 } else {
(...skipping 15 matching lines...) Expand all
3288 3419
3289 if (op == Token::NOT) { 3420 if (op == Token::NOT) {
3290 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, 3421 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
3291 false_target(), true_target(), true); 3422 false_target(), true_target(), true);
3292 cc_reg_ = NegateCondition(cc_reg_); 3423 cc_reg_ = NegateCondition(cc_reg_);
3293 3424
3294 } else if (op == Token::DELETE) { 3425 } else if (op == Token::DELETE) {
3295 Property* property = node->expression()->AsProperty(); 3426 Property* property = node->expression()->AsProperty();
3296 if (property != NULL) { 3427 if (property != NULL) {
3297 Load(property->obj()); 3428 Load(property->obj());
3429 frame_->SpillAll();
3298 Load(property->key()); 3430 Load(property->key());
3431 frame_->SpillAll();
3299 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 3432 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
3300 frame_->EmitPush(eax); 3433 frame_->EmitPush(eax);
3301 return; 3434 return;
3302 } 3435 }
3303 3436
3304 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 3437 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
3305 if (variable != NULL) { 3438 if (variable != NULL) {
3306 Slot* slot = variable->slot(); 3439 Slot* slot = variable->slot();
3307 if (variable->is_global()) { 3440 if (variable->is_global()) {
3308 LoadGlobal(); 3441 LoadGlobal();
(...skipping 15 matching lines...) Expand all
3324 return; 3457 return;
3325 } 3458 }
3326 3459
3327 // Default: Result of deleting non-global, not dynamically 3460 // Default: Result of deleting non-global, not dynamically
3328 // introduced variables is false. 3461 // introduced variables is false.
3329 frame_->EmitPush(Immediate(Factory::false_value())); 3462 frame_->EmitPush(Immediate(Factory::false_value()));
3330 3463
3331 } else { 3464 } else {
3332 // Default: Result of deleting expressions is true. 3465 // Default: Result of deleting expressions is true.
3333 Load(node->expression()); // may have side-effects 3466 Load(node->expression()); // may have side-effects
3467 frame_->SpillAll();
3334 __ Set(frame_->Top(), Immediate(Factory::true_value())); 3468 __ Set(frame_->Top(), Immediate(Factory::true_value()));
3335 } 3469 }
3336 3470
3337 } else if (op == Token::TYPEOF) { 3471 } else if (op == Token::TYPEOF) {
3338 // Special case for loading the typeof expression; see comment on 3472 // Special case for loading the typeof expression; see comment on
3339 // LoadTypeofExpression(). 3473 // LoadTypeofExpression().
3340 LoadTypeofExpression(node->expression()); 3474 LoadTypeofExpression(node->expression());
3341 frame_->CallRuntime(Runtime::kTypeof, 1); 3475 frame_->CallRuntime(Runtime::kTypeof, 1);
3342 frame_->EmitPush(eax); 3476 frame_->EmitPush(eax);
3343 3477
3344 } else { 3478 } else {
3345 Load(node->expression()); 3479 Load(node->expression());
3480 frame_->SpillAll();
3346 switch (op) { 3481 switch (op) {
3347 case Token::NOT: 3482 case Token::NOT:
3348 case Token::DELETE: 3483 case Token::DELETE:
3349 case Token::TYPEOF: 3484 case Token::TYPEOF:
3350 UNREACHABLE(); // handled above 3485 UNREACHABLE(); // handled above
3351 break; 3486 break;
3352 3487
3353 case Token::SUB: { 3488 case Token::SUB: {
3354 UnarySubStub stub; 3489 UnarySubStub stub;
3355 // TODO(1222589): remove dependency of TOS being cached inside stub 3490 // TODO(1222589): remove dependency of TOS being cached inside stub
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
3584 Branch(false, false_target()); 3719 Branch(false, false_target());
3585 } 3720 }
3586 3721
3587 if (frame_ != NULL || is_true.is_linked()) { 3722 if (frame_ != NULL || is_true.is_linked()) {
3588 // Evaluate right side expression. 3723 // Evaluate right side expression.
3589 is_true.Bind(); 3724 is_true.Bind();
3590 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(), 3725 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
3591 false_target(), false); 3726 false_target(), false);
3592 } 3727 }
3593 } else { 3728 } else {
3729 frame_->SpillAll();
3594 // We have a materialized value on the frame. 3730 // We have a materialized value on the frame.
3595 JumpTarget pop_and_continue(this); 3731 JumpTarget pop_and_continue(this);
3596 JumpTarget exit(this); 3732 JumpTarget exit(this);
3597 3733
3598 // Avoid popping the result if it converts to 'false' using the 3734 // Avoid popping the result if it converts to 'false' using the
3599 // standard ToBoolean() conversion as described in ECMA-262, section 3735 // standard ToBoolean() conversion as described in ECMA-262, section
3600 // 9.2, page 30. 3736 // 9.2, page 30.
3601 // 3737 //
3602 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3738 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3603 __ mov(eax, frame_->Top()); 3739 __ mov(eax, frame_->Top());
3604 frame_->EmitPush(eax); 3740 frame_->EmitPush(eax);
3605 ToBoolean(&pop_and_continue, &exit); 3741 ToBoolean(&pop_and_continue, &exit);
3606 Branch(false, &exit); 3742 Branch(false, &exit);
3607 3743
3608 // Pop the result of evaluating the first part. 3744 // Pop the result of evaluating the first part.
3609 pop_and_continue.Bind(); 3745 pop_and_continue.Bind();
3610 frame_->Drop(); 3746 frame_->Drop();
3611 3747
3612 // Evaluate right side expression. 3748 // Evaluate right side expression.
3613 is_true.Bind(); 3749 is_true.Bind();
3614 Load(node->right()); 3750 Load(node->right());
3751 frame_->SpillAll();
3615 3752
3616 // Exit (always with a materialized value). 3753 // Exit (always with a materialized value).
3617 exit.Bind(); 3754 exit.Bind();
3618 } 3755 }
3619 3756
3620 } else if (op == Token::OR) { 3757 } else if (op == Token::OR) {
3621 JumpTarget is_false(this); 3758 JumpTarget is_false(this);
3622 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(), 3759 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(),
3623 &is_false, false); 3760 &is_false, false);
3624 if (has_cc() || frame_ == NULL) { 3761 if (has_cc() || frame_ == NULL) {
3625 if (has_cc()) { 3762 if (has_cc()) {
3626 ASSERT(frame_ != NULL); 3763 ASSERT(frame_ != NULL);
3627 Branch(true, true_target()); 3764 Branch(true, true_target());
3628 } 3765 }
3629 3766
3630 if (frame_ != NULL || is_false.is_linked()) { 3767 if (frame_ != NULL || is_false.is_linked()) {
3631 // Evaluate right side expression. 3768 // Evaluate right side expression.
3632 is_false.Bind(); 3769 is_false.Bind();
3633 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(), 3770 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
3634 false_target(), false); 3771 false_target(), false);
3635 } 3772 }
3636 3773
3637 } else { 3774 } else {
3775 frame_->SpillAll();
3638 // We have a materialized value on the frame. 3776 // We have a materialized value on the frame.
3639 JumpTarget pop_and_continue(this); 3777 JumpTarget pop_and_continue(this);
3640 JumpTarget exit(this); 3778 JumpTarget exit(this);
3641 3779
3642 // Avoid popping the result if it converts to 'true' using the 3780 // Avoid popping the result if it converts to 'true' using the
3643 // standard ToBoolean() conversion as described in ECMA-262, 3781 // standard ToBoolean() conversion as described in ECMA-262,
3644 // section 9.2, page 30. 3782 // section 9.2, page 30.
3645 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3783 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3646 __ mov(eax, frame_->Top()); 3784 __ mov(eax, frame_->Top());
3647 frame_->EmitPush(eax); 3785 frame_->EmitPush(eax);
3648 ToBoolean(&exit, &pop_and_continue); 3786 ToBoolean(&exit, &pop_and_continue);
3649 Branch(true, &exit); 3787 Branch(true, &exit);
3650 3788
3651 // Pop the result of evaluating the first part. 3789 // Pop the result of evaluating the first part.
3652 pop_and_continue.Bind(); 3790 pop_and_continue.Bind();
3653 frame_->Drop(); 3791 frame_->Drop();
3654 3792
3655 // Evaluate right side expression. 3793 // Evaluate right side expression.
3656 is_false.Bind(); 3794 is_false.Bind();
3657 Load(node->right()); 3795 Load(node->right());
3796 frame_->SpillAll();
3658 3797
3659 // Exit (always with a materialized value). 3798 // Exit (always with a materialized value).
3660 exit.Bind(); 3799 exit.Bind();
3661 } 3800 }
3662 3801
3663 } else { 3802 } else {
3664 // NOTE: The code below assumes that the slow cases (calls to runtime) 3803 // NOTE: The code below assumes that the slow cases (calls to runtime)
3665 // never return a constant/immutable object. 3804 // never return a constant/immutable object.
3666 OverwriteMode overwrite_mode = NO_OVERWRITE; 3805 OverwriteMode overwrite_mode = NO_OVERWRITE;
3667 if (node->left()->AsBinaryOperation() != NULL && 3806 if (node->left()->AsBinaryOperation() != NULL &&
3668 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) { 3807 node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
3669 overwrite_mode = OVERWRITE_LEFT; 3808 overwrite_mode = OVERWRITE_LEFT;
3670 } else if (node->right()->AsBinaryOperation() != NULL && 3809 } else if (node->right()->AsBinaryOperation() != NULL &&
3671 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) { 3810 node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
3672 overwrite_mode = OVERWRITE_RIGHT; 3811 overwrite_mode = OVERWRITE_RIGHT;
3673 } 3812 }
3674 3813
3675 // Optimize for the case where (at least) one of the expressions 3814 // Optimize for the case where (at least) one of the expressions
3676 // is a literal small integer. 3815 // is a literal small integer.
3677 Literal* lliteral = node->left()->AsLiteral(); 3816 Literal* lliteral = node->left()->AsLiteral();
3678 Literal* rliteral = node->right()->AsLiteral(); 3817 Literal* rliteral = node->right()->AsLiteral();
3679 3818
3680 if (IsInlineSmi(rliteral)) { 3819 if (IsInlineSmi(rliteral)) {
3681 Load(node->left()); 3820 Load(node->left());
3821 frame_->SpillAll();
3682 SmiOperation(node->op(), node->type(), rliteral->handle(), false, 3822 SmiOperation(node->op(), node->type(), rliteral->handle(), false,
3683 overwrite_mode); 3823 overwrite_mode);
3684 } else if (IsInlineSmi(lliteral)) { 3824 } else if (IsInlineSmi(lliteral)) {
3685 Load(node->right()); 3825 Load(node->right());
3826 frame_->SpillAll();
3686 SmiOperation(node->op(), node->type(), lliteral->handle(), true, 3827 SmiOperation(node->op(), node->type(), lliteral->handle(), true,
3687 overwrite_mode); 3828 overwrite_mode);
3688 } else { 3829 } else {
3689 Load(node->left()); 3830 Load(node->left());
3831 frame_->SpillAll();
3690 Load(node->right()); 3832 Load(node->right());
3833 frame_->SpillAll();
3691 GenericBinaryOperation(node->op(), node->type(), overwrite_mode); 3834 GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
3692 } 3835 }
3693 } 3836 }
3694 } 3837 }
3695 3838
3696 3839
3697 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3840 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3698 frame_->SpillAll(); 3841 frame_->SpillAll();
3699 frame_->EmitPush(frame_->Function()); 3842 frame_->EmitPush(frame_->Function());
3700 } 3843 }
(...skipping 25 matching lines...) Expand all
3726 // instead of calling the (very) general runtime routine for checking 3869 // instead of calling the (very) general runtime routine for checking
3727 // equality. 3870 // equality.
3728 if (op == Token::EQ || op == Token::EQ_STRICT) { 3871 if (op == Token::EQ || op == Token::EQ_STRICT) {
3729 bool left_is_null = 3872 bool left_is_null =
3730 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 3873 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
3731 bool right_is_null = 3874 bool right_is_null =
3732 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 3875 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
3733 // The 'null' value can only be equal to 'null' or 'undefined'. 3876 // The 'null' value can only be equal to 'null' or 'undefined'.
3734 if (left_is_null || right_is_null) { 3877 if (left_is_null || right_is_null) {
3735 Load(left_is_null ? right : left); 3878 Load(left_is_null ? right : left);
3879 frame_->SpillAll();
3736 frame_->EmitPop(eax); 3880 frame_->EmitPop(eax);
3737 __ cmp(eax, Factory::null_value()); 3881 __ cmp(eax, Factory::null_value());
3738 3882
3739 // The 'null' value is only equal to 'undefined' if using non-strict 3883 // The 'null' value is only equal to 'undefined' if using non-strict
3740 // comparisons. 3884 // comparisons.
3741 if (op != Token::EQ_STRICT) { 3885 if (op != Token::EQ_STRICT) {
3742 true_target()->Branch(equal); 3886 true_target()->Branch(equal);
3743 3887
3744 __ cmp(eax, Factory::undefined_value()); 3888 __ cmp(eax, Factory::undefined_value());
3745 true_target()->Branch(equal); 3889 true_target()->Branch(equal);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
3871 cc = greater; 4015 cc = greater;
3872 break; 4016 break;
3873 case Token::LTE: 4017 case Token::LTE:
3874 cc = less_equal; 4018 cc = less_equal;
3875 break; 4019 break;
3876 case Token::GTE: 4020 case Token::GTE:
3877 cc = greater_equal; 4021 cc = greater_equal;
3878 break; 4022 break;
3879 case Token::IN: { 4023 case Token::IN: {
3880 Load(left); 4024 Load(left);
4025 frame_->SpillAll();
3881 Load(right); 4026 Load(right);
4027 frame_->SpillAll();
3882 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); 4028 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
3883 frame_->EmitPush(eax); // push the result 4029 frame_->EmitPush(eax); // push the result
3884 return; 4030 return;
3885 } 4031 }
3886 case Token::INSTANCEOF: { 4032 case Token::INSTANCEOF: {
3887 Load(left); 4033 Load(left);
4034 frame_->SpillAll();
3888 Load(right); 4035 Load(right);
4036 frame_->SpillAll();
3889 InstanceofStub stub; 4037 InstanceofStub stub;
3890 frame_->CallStub(&stub, 2); 4038 frame_->CallStub(&stub, 2);
3891 __ test(eax, Operand(eax)); 4039 __ test(eax, Operand(eax));
3892 cc_reg_ = zero; 4040 cc_reg_ = zero;
3893 return; 4041 return;
3894 } 4042 }
3895 default: 4043 default:
3896 UNREACHABLE(); 4044 UNREACHABLE();
3897 } 4045 }
3898 4046
3899 // Optimize for the case where (at least) one of the expressions 4047 // Optimize for the case where (at least) one of the expressions
3900 // is a literal small integer. 4048 // is a literal small integer.
3901 if (IsInlineSmi(left->AsLiteral())) { 4049 if (IsInlineSmi(left->AsLiteral())) {
3902 Load(right); 4050 Load(right);
4051 frame_->SpillAll();
3903 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict); 4052 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict);
3904 return; 4053 return;
3905 } 4054 }
3906 if (IsInlineSmi(right->AsLiteral())) { 4055 if (IsInlineSmi(right->AsLiteral())) {
3907 Load(left); 4056 Load(left);
4057 frame_->SpillAll();
3908 SmiComparison(cc, right->AsLiteral()->handle(), strict); 4058 SmiComparison(cc, right->AsLiteral()->handle(), strict);
3909 return; 4059 return;
3910 } 4060 }
3911 4061
3912 Load(left); 4062 Load(left);
4063 frame_->SpillAll();
3913 Load(right); 4064 Load(right);
4065 frame_->SpillAll();
3914 Comparison(cc, strict); 4066 Comparison(cc, strict);
3915 } 4067 }
3916 4068
3917 4069
3918 void CodeGenerator::RecordStatementPosition(Node* node) { 4070 void CodeGenerator::RecordStatementPosition(Node* node) {
3919 if (FLAG_debug_info) { 4071 if (FLAG_debug_info) {
3920 int pos = node->statement_pos(); 4072 int pos = node->statement_pos();
3921 if (pos != RelocInfo::kNoPosition) { 4073 if (pos != RelocInfo::kNoPosition) {
3922 __ RecordStatementPosition(pos); 4074 __ RecordStatementPosition(pos);
3923 } 4075 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
4018 void Reference::SetValue(InitState init_state) { 4170 void Reference::SetValue(InitState init_state) {
4019 ASSERT(!is_illegal()); 4171 ASSERT(!is_illegal());
4020 ASSERT(!cgen_->has_cc()); 4172 ASSERT(!cgen_->has_cc());
4021 MacroAssembler* masm = cgen_->masm(); 4173 MacroAssembler* masm = cgen_->masm();
4022 VirtualFrame* frame = cgen_->frame(); 4174 VirtualFrame* frame = cgen_->frame();
4023 switch (type_) { 4175 switch (type_) {
4024 case SLOT: { 4176 case SLOT: {
4025 Comment cmnt(masm, "[ Store to Slot"); 4177 Comment cmnt(masm, "[ Store to Slot");
4026 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4178 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4027 ASSERT(slot != NULL); 4179 ASSERT(slot != NULL);
4028 if (slot->type() == Slot::LOOKUP) { 4180 cgen_->StoreToSlot(slot, init_state);
4029 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
4030
4031 // For now, just do a runtime call.
4032 frame->EmitPush(esi);
4033 frame->EmitPush(Immediate(slot->var()->name()));
4034
4035 if (init_state == CONST_INIT) {
4036 // Same as the case for a normal store, but ignores attribute
4037 // (e.g. READ_ONLY) of context slot so that we can initialize
4038 // const properties (introduced via eval("const foo = (some
4039 // expr);")). Also, uses the current function context instead of
4040 // the top context.
4041 //
4042 // Note that we must declare the foo upon entry of eval(), via a
4043 // context slot declaration, but we cannot initialize it at the
4044 // same time, because the const declaration may be at the end of
4045 // the eval code (sigh...) and the const variable may have been
4046 // used before (where its value is 'undefined'). Thus, we can only
4047 // do the initialization when we actually encounter the expression
4048 // and when the expression operands are defined and valid, and
4049 // thus we need the split into 2 operations: declaration of the
4050 // context slot followed by initialization.
4051 frame->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
4052 } else {
4053 frame->CallRuntime(Runtime::kStoreContextSlot, 3);
4054 }
4055 // Storing a variable must keep the (new) value on the expression
4056 // stack. This is necessary for compiling chained assignment
4057 // expressions.
4058 frame->EmitPush(eax);
4059
4060 } else {
4061 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
4062
4063 JumpTarget exit(cgen_);
4064 if (init_state == CONST_INIT) {
4065 ASSERT(slot->var()->mode() == Variable::CONST);
4066 // Only the first const initialization must be executed (the slot
4067 // still contains 'the hole' value). When the assignment is
4068 // executed, the code is identical to a normal store (see below).
4069 Comment cmnt(masm, "[ Init const");
4070 __ mov(eax, cgen_->SlotOperand(slot, ecx));
4071 __ cmp(eax, Factory::the_hole_value());
4072 exit.Branch(not_equal);
4073 }
4074
4075 // We must execute the store. Storing a variable must keep the
4076 // (new) value on the stack. This is necessary for compiling
4077 // assignment expressions.
4078 //
4079 // Note: We will reach here even with slot->var()->mode() ==
4080 // Variable::CONST because of const declarations which will
4081 // initialize consts to 'the hole' value and by doing so, end up
4082 // calling this code.
4083 frame->EmitPop(eax);
4084 __ mov(cgen_->SlotOperand(slot, ecx), eax);
4085 frame->EmitPush(eax); // RecordWrite may destroy the value in eax.
4086 if (slot->type() == Slot::CONTEXT) {
4087 // ecx is loaded with context when calling SlotOperand above.
4088 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
4089 __ RecordWrite(ecx, offset, eax, ebx);
4090 }
4091 // If we definitely did not jump over the assignment, we do not need
4092 // to bind the exit label. Doing so can defeat peephole
4093 // optimization.
4094 if (init_state == CONST_INIT) {
4095 exit.Bind();
4096 }
4097 }
4098 break; 4181 break;
4099 } 4182 }
4100 4183
4101 case NAMED: { 4184 case NAMED: {
4185 frame->SpillAll();
iposva 2008/12/03 07:04:40 Could this SpillAll() be moved after the EmitPop(e
Kevin Millikin (Chromium) 2008/12/03 15:08:38 Eventually when this code is reworked. Right now
4102 Comment cmnt(masm, "[ Store to named Property"); 4186 Comment cmnt(masm, "[ Store to named Property");
4103 // Call the appropriate IC code. 4187 // Call the appropriate IC code.
4104 Handle<String> name(GetName()); 4188 Handle<String> name(GetName());
4105 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 4189 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
4106 // TODO(1222589): Make the IC grab the values from the stack. 4190 // TODO(1222589): Make the IC grab the values from the stack.
4107 frame->EmitPop(eax); 4191 frame->EmitPop(eax);
4108 // Setup the name register. 4192 // Setup the name register.
4109 __ mov(ecx, name); 4193 __ mov(ecx, name);
4110 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4194 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4111 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4195 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4112 break; 4196 break;
4113 } 4197 }
4114 4198
4115 case KEYED: { 4199 case KEYED: {
4200 frame->SpillAll();
iposva 2008/12/03 07:04:40 ditto.
4116 Comment cmnt(masm, "[ Store to keyed Property"); 4201 Comment cmnt(masm, "[ Store to keyed Property");
4117 Property* property = expression_->AsProperty(); 4202 Property* property = expression_->AsProperty();
4118 ASSERT(property != NULL); 4203 ASSERT(property != NULL);
4119 __ RecordPosition(property->position()); 4204 __ RecordPosition(property->position());
4120 // Call IC code. 4205 // Call IC code.
4121 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 4206 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
4122 // TODO(1222589): Make the IC grab the values from the stack. 4207 // TODO(1222589): Make the IC grab the values from the stack.
4123 frame->EmitPop(eax); 4208 frame->EmitPop(eax);
4124 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4209 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4125 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4210 frame->EmitPush(eax); // IC call leaves result in eax, push it out
(...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after
5350 5435
5351 // Slow-case: Go through the JavaScript implementation. 5436 // Slow-case: Go through the JavaScript implementation.
5352 __ bind(&slow); 5437 __ bind(&slow);
5353 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5438 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5354 } 5439 }
5355 5440
5356 5441
5357 #undef __ 5442 #undef __
5358 5443
5359 } } // namespace v8::internal 5444 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/virtual-frame-ia32.h » ('j') | src/virtual-frame-ia32.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698