Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 // (partially) translated into branches, or it may have set the condition | 375 // (partially) translated into branches, or it may have set the condition |
| 376 // code register. If force_cc is set, the value is forced to set the | 376 // code register. If force_cc is set, the value is forced to set the |
| 377 // condition code register and no value is pushed. If the condition code | 377 // condition code register and no value is pushed. If the condition code |
| 378 // register was set, has_cc() is true and cc_reg_ contains the condition to | 378 // register was set, has_cc() is true and cc_reg_ contains the condition to |
| 379 // test for 'true'. | 379 // test for 'true'. |
| 380 void CodeGenerator::LoadCondition(Expression* x, | 380 void CodeGenerator::LoadCondition(Expression* x, |
| 381 TypeofState typeof_state, | 381 TypeofState typeof_state, |
| 382 JumpTarget* true_target, | 382 JumpTarget* true_target, |
| 383 JumpTarget* false_target, | 383 JumpTarget* false_target, |
| 384 bool force_cc) { | 384 bool force_cc) { |
| 385 #ifdef DEBUG | |
| 386 int original_height = frame_->height(); | |
| 387 #endif | |
| 385 ASSERT(!in_spilled_code()); | 388 ASSERT(!in_spilled_code()); |
| 386 ASSERT(!has_cc()); | 389 ASSERT(!has_cc()); |
| 387 | 390 |
| 388 { CodeGenState new_state(this, typeof_state, true_target, false_target); | 391 { CodeGenState new_state(this, typeof_state, true_target, false_target); |
| 389 Visit(x); | 392 Visit(x); |
| 390 } | 393 } |
| 391 if (force_cc && frame_ != NULL && !has_cc()) { | 394 if (force_cc && frame_ != NULL && !has_cc()) { |
| 392 // Convert the TOS value to a boolean in the condition code register. | 395 // Convert the TOS value to a boolean in the condition code register. |
| 393 ToBoolean(true_target, false_target); | 396 ToBoolean(true_target, false_target); |
| 394 } | 397 } |
| 395 ASSERT(!force_cc || frame_ == NULL || has_cc()); | 398 ASSERT(!force_cc || !has_valid_frame() || has_cc()); |
| 399 ASSERT(!has_valid_frame() || | |
| 400 (has_cc() && frame_->height() == original_height) || | |
| 401 (!has_cc() && frame_->height() == original_height + 1)); | |
| 396 } | 402 } |
| 397 | 403 |
| 398 | 404 |
| 399 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 405 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { |
| 406 #ifdef DEBUG | |
| 407 int original_height = frame_->height(); | |
| 408 #endif | |
| 400 ASSERT(!in_spilled_code()); | 409 ASSERT(!in_spilled_code()); |
| 401 JumpTarget true_target(this); | 410 JumpTarget true_target(this); |
| 402 JumpTarget false_target(this); | 411 JumpTarget false_target(this); |
| 403 LoadCondition(x, typeof_state, &true_target, &false_target, false); | 412 LoadCondition(x, typeof_state, &true_target, &false_target, false); |
| 404 | 413 |
| 405 if (has_cc()) { | 414 if (has_cc()) { |
| 406 // Convert cc_reg_ into a boolean value. | 415 // Convert cc_reg_ into a boolean value. |
| 407 JumpTarget loaded(this); | 416 JumpTarget loaded(this); |
| 408 JumpTarget materialize_true(this); | 417 JumpTarget materialize_true(this); |
| 409 materialize_true.Branch(cc_reg_); | 418 materialize_true.Branch(cc_reg_); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 438 } | 447 } |
| 439 // Load "false" if necessary. | 448 // Load "false" if necessary. |
| 440 if (false_target.is_linked()) { | 449 if (false_target.is_linked()) { |
| 441 false_target.Bind(); | 450 false_target.Bind(); |
| 442 __ mov(r0, Operand(Factory::false_value())); | 451 __ mov(r0, Operand(Factory::false_value())); |
| 443 frame_->EmitPush(r0); | 452 frame_->EmitPush(r0); |
| 444 } | 453 } |
| 445 // A value is loaded on all paths reaching this point. | 454 // A value is loaded on all paths reaching this point. |
| 446 loaded.Bind(); | 455 loaded.Bind(); |
| 447 } | 456 } |
| 448 ASSERT(frame_ != NULL); | 457 ASSERT(has_valid_frame()); |
| 449 ASSERT(!has_cc()); | 458 ASSERT(!has_cc()); |
| 459 ASSERT(frame_->height() == original_height + 1); | |
| 450 } | 460 } |
| 451 | 461 |
| 452 | 462 |
| 453 void CodeGenerator::LoadGlobal() { | 463 void CodeGenerator::LoadGlobal() { |
| 454 VirtualFrame::SpilledScope spilled_scope(this); | 464 VirtualFrame::SpilledScope spilled_scope(this); |
| 455 __ ldr(r0, GlobalObject()); | 465 __ ldr(r0, GlobalObject()); |
| 456 frame_->EmitPush(r0); | 466 frame_->EmitPush(r0); |
| 457 } | 467 } |
| 458 | 468 |
| 459 | 469 |
| (...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1078 VirtualFrame::SpilledScope spilled_scope(this); | 1088 VirtualFrame::SpilledScope spilled_scope(this); |
| 1079 if (FLAG_check_stack) { | 1089 if (FLAG_check_stack) { |
| 1080 Comment cmnt(masm_, "[ check stack"); | 1090 Comment cmnt(masm_, "[ check stack"); |
| 1081 StackCheckStub stub; | 1091 StackCheckStub stub; |
| 1082 frame_->CallStub(&stub, 0); | 1092 frame_->CallStub(&stub, 0); |
| 1083 } | 1093 } |
| 1084 } | 1094 } |
| 1085 | 1095 |
| 1086 | 1096 |
| 1087 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 1097 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 1098 #ifdef DEBUG | |
| 1099 int original_height = frame_->height(); | |
| 1100 #endif | |
| 1088 VirtualFrame::SpilledScope spilled_scope(this); | 1101 VirtualFrame::SpilledScope spilled_scope(this); |
| 1089 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { | 1102 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { |
| 1090 VisitAndSpill(statements->at(i)); | 1103 VisitAndSpill(statements->at(i)); |
| 1091 } | 1104 } |
| 1105 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
| 1092 } | 1106 } |
| 1093 | 1107 |
| 1094 | 1108 |
| 1095 void CodeGenerator::VisitBlock(Block* node) { | 1109 void CodeGenerator::VisitBlock(Block* node) { |
| 1110 #ifdef DEBUG | |
| 1111 int original_height = frame_->height(); | |
| 1112 #endif | |
| 1096 VirtualFrame::SpilledScope spilled_scope(this); | 1113 VirtualFrame::SpilledScope spilled_scope(this); |
| 1097 Comment cmnt(masm_, "[ Block"); | 1114 Comment cmnt(masm_, "[ Block"); |
| 1098 CodeForStatementPosition(node); | 1115 CodeForStatementPosition(node); |
| 1099 node->set_break_stack_height(break_stack_height_); | 1116 node->set_break_stack_height(break_stack_height_); |
| 1100 node->break_target()->Initialize(this); | 1117 node->break_target()->Initialize(this); |
| 1101 VisitStatementsAndSpill(node->statements()); | 1118 VisitStatementsAndSpill(node->statements()); |
| 1102 if (node->break_target()->is_linked()) { | 1119 if (node->break_target()->is_linked()) { |
| 1103 node->break_target()->Bind(); | 1120 node->break_target()->Bind(); |
| 1104 } | 1121 } |
| 1122 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
| 1105 } | 1123 } |
| 1106 | 1124 |
| 1107 | 1125 |
| 1108 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1126 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 1109 VirtualFrame::SpilledScope spilled_scope(this); | 1127 VirtualFrame::SpilledScope spilled_scope(this); |
| 1110 __ mov(r0, Operand(pairs)); | 1128 __ mov(r0, Operand(pairs)); |
| 1111 frame_->EmitPush(r0); | 1129 frame_->EmitPush(r0); |
| 1112 frame_->EmitPush(cp); | 1130 frame_->EmitPush(cp); |
| 1113 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); | 1131 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); |
| 1114 frame_->EmitPush(r0); | 1132 frame_->EmitPush(r0); |
| 1115 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 1133 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); |
| 1116 // The result is discarded. | 1134 // The result is discarded. |
| 1117 } | 1135 } |
| 1118 | 1136 |
| 1119 | 1137 |
| 1120 void CodeGenerator::VisitDeclaration(Declaration* node) { | 1138 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 1139 #ifdef DEBUG | |
| 1140 int original_height = frame_->height(); | |
| 1141 #endif | |
| 1121 VirtualFrame::SpilledScope spilled_scope(this); | 1142 VirtualFrame::SpilledScope spilled_scope(this); |
| 1122 Comment cmnt(masm_, "[ Declaration"); | 1143 Comment cmnt(masm_, "[ Declaration"); |
| 1123 CodeForStatementPosition(node); | 1144 CodeForStatementPosition(node); |
| 1124 Variable* var = node->proxy()->var(); | 1145 Variable* var = node->proxy()->var(); |
| 1125 ASSERT(var != NULL); // must have been resolved | 1146 ASSERT(var != NULL); // must have been resolved |
| 1126 Slot* slot = var->slot(); | 1147 Slot* slot = var->slot(); |
| 1127 | 1148 |
| 1128 // If it was not possible to allocate the variable at compile time, | 1149 // If it was not possible to allocate the variable at compile time, |
| 1129 // we need to "declare" it at runtime to make sure it actually | 1150 // we need to "declare" it at runtime to make sure it actually |
| 1130 // exists in the local context. | 1151 // exists in the local context. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1149 __ mov(r0, Operand(Factory::the_hole_value())); | 1170 __ mov(r0, Operand(Factory::the_hole_value())); |
| 1150 frame_->EmitPush(r0); | 1171 frame_->EmitPush(r0); |
| 1151 } else if (node->fun() != NULL) { | 1172 } else if (node->fun() != NULL) { |
| 1152 LoadAndSpill(node->fun()); | 1173 LoadAndSpill(node->fun()); |
| 1153 } else { | 1174 } else { |
| 1154 __ mov(r0, Operand(0)); // no initial value! | 1175 __ mov(r0, Operand(0)); // no initial value! |
| 1155 frame_->EmitPush(r0); | 1176 frame_->EmitPush(r0); |
| 1156 } | 1177 } |
| 1157 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); | 1178 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 1158 // Ignore the return value (declarations are statements). | 1179 // Ignore the return value (declarations are statements). |
| 1180 ASSERT(frame_->height() == original_height); | |
| 1159 return; | 1181 return; |
| 1160 } | 1182 } |
| 1161 | 1183 |
| 1162 ASSERT(!var->is_global()); | 1184 ASSERT(!var->is_global()); |
| 1163 | 1185 |
| 1164 // If we have a function or a constant, we need to initialize the variable. | 1186 // If we have a function or a constant, we need to initialize the variable. |
| 1165 Expression* val = NULL; | 1187 Expression* val = NULL; |
| 1166 if (node->mode() == Variable::CONST) { | 1188 if (node->mode() == Variable::CONST) { |
| 1167 val = new Literal(Factory::the_hole_value()); | 1189 val = new Literal(Factory::the_hole_value()); |
| 1168 } else { | 1190 } else { |
| 1169 val = node->fun(); // NULL if we don't have a function | 1191 val = node->fun(); // NULL if we don't have a function |
| 1170 } | 1192 } |
| 1171 | 1193 |
| 1172 if (val != NULL) { | 1194 if (val != NULL) { |
| 1173 { | 1195 { |
| 1174 // Set initial value. | 1196 // Set initial value. |
| 1175 Reference target(this, node->proxy()); | 1197 Reference target(this, node->proxy()); |
| 1176 LoadAndSpill(val); | 1198 LoadAndSpill(val); |
| 1177 target.SetValue(NOT_CONST_INIT); | 1199 target.SetValue(NOT_CONST_INIT); |
| 1178 // The reference is removed from the stack (preserving TOS) when | 1200 // The reference is removed from the stack (preserving TOS) when |
| 1179 // it goes out of scope. | 1201 // it goes out of scope. |
| 1180 } | 1202 } |
| 1181 // Get rid of the assigned value (declarations are statements). | 1203 // Get rid of the assigned value (declarations are statements). |
| 1182 frame_->Drop(); | 1204 frame_->Drop(); |
| 1183 } | 1205 } |
| 1206 ASSERT(frame_->height() == original_height); | |
| 1184 } | 1207 } |
| 1185 | 1208 |
| 1186 | 1209 |
| 1187 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1210 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
| 1211 #ifdef DEBUG | |
| 1212 int original_height = frame_->height(); | |
| 1213 #endif | |
| 1188 VirtualFrame::SpilledScope spilled_scope(this); | 1214 VirtualFrame::SpilledScope spilled_scope(this); |
| 1189 Comment cmnt(masm_, "[ ExpressionStatement"); | 1215 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 1190 CodeForStatementPosition(node); | 1216 CodeForStatementPosition(node); |
| 1191 Expression* expression = node->expression(); | 1217 Expression* expression = node->expression(); |
| 1192 expression->MarkAsStatement(); | 1218 expression->MarkAsStatement(); |
| 1193 LoadAndSpill(expression); | 1219 LoadAndSpill(expression); |
| 1194 frame_->Drop(); | 1220 frame_->Drop(); |
| 1221 ASSERT(frame_->height() == original_height); | |
| 1195 } | 1222 } |
| 1196 | 1223 |
| 1197 | 1224 |
| 1198 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1225 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
| 1226 #ifdef DEBUG | |
| 1227 int original_height = frame_->height(); | |
| 1228 #endif | |
| 1199 VirtualFrame::SpilledScope spilled_scope(this); | 1229 VirtualFrame::SpilledScope spilled_scope(this); |
| 1200 Comment cmnt(masm_, "// EmptyStatement"); | 1230 Comment cmnt(masm_, "// EmptyStatement"); |
| 1201 CodeForStatementPosition(node); | 1231 CodeForStatementPosition(node); |
| 1202 // nothing to do | 1232 // nothing to do |
| 1233 ASSERT(frame_->height() == original_height); | |
| 1203 } | 1234 } |
| 1204 | 1235 |
| 1205 | 1236 |
| 1206 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 1237 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
| 1238 #ifdef DEBUG | |
| 1239 int original_height = frame_->height(); | |
| 1240 #endif | |
| 1207 VirtualFrame::SpilledScope spilled_scope(this); | 1241 VirtualFrame::SpilledScope spilled_scope(this); |
| 1208 Comment cmnt(masm_, "[ IfStatement"); | 1242 Comment cmnt(masm_, "[ IfStatement"); |
| 1209 // Generate different code depending on which parts of the if statement | 1243 // Generate different code depending on which parts of the if statement |
| 1210 // are present or not. | 1244 // are present or not. |
| 1211 bool has_then_stm = node->HasThenStatement(); | 1245 bool has_then_stm = node->HasThenStatement(); |
| 1212 bool has_else_stm = node->HasElseStatement(); | 1246 bool has_else_stm = node->HasElseStatement(); |
| 1213 | 1247 |
| 1214 CodeForStatementPosition(node); | 1248 CodeForStatementPosition(node); |
| 1215 | 1249 |
| 1216 JumpTarget exit(this); | 1250 JumpTarget exit(this); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1282 } else { | 1316 } else { |
| 1283 frame_->Drop(); | 1317 frame_->Drop(); |
| 1284 } | 1318 } |
| 1285 } | 1319 } |
| 1286 } | 1320 } |
| 1287 | 1321 |
| 1288 // end | 1322 // end |
| 1289 if (exit.is_linked()) { | 1323 if (exit.is_linked()) { |
| 1290 exit.Bind(); | 1324 exit.Bind(); |
| 1291 } | 1325 } |
| 1326 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
| 1292 } | 1327 } |
| 1293 | 1328 |
| 1294 | 1329 |
| 1295 void CodeGenerator::CleanStack(int num_bytes) { | 1330 void CodeGenerator::CleanStack(int num_bytes) { |
| 1296 VirtualFrame::SpilledScope spilled_scope(this); | 1331 VirtualFrame::SpilledScope spilled_scope(this); |
| 1297 ASSERT(num_bytes % kPointerSize == 0); | 1332 ASSERT(num_bytes % kPointerSize == 0); |
| 1298 frame_->Drop(num_bytes / kPointerSize); | 1333 frame_->Drop(num_bytes / kPointerSize); |
| 1299 } | 1334 } |
| 1300 | 1335 |
| 1301 | 1336 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1335 // returning thus making it easier to merge. | 1370 // returning thus making it easier to merge. |
| 1336 frame_->EmitPop(r0); | 1371 frame_->EmitPop(r0); |
| 1337 frame_->PrepareForReturn(); | 1372 frame_->PrepareForReturn(); |
| 1338 | 1373 |
| 1339 function_return_.Jump(); | 1374 function_return_.Jump(); |
| 1340 } | 1375 } |
| 1341 } | 1376 } |
| 1342 | 1377 |
| 1343 | 1378 |
| 1344 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1379 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
| 1380 #ifdef DEBUG | |
| 1381 int original_height = frame_->height(); | |
| 1382 #endif | |
| 1345 VirtualFrame::SpilledScope spilled_scope(this); | 1383 VirtualFrame::SpilledScope spilled_scope(this); |
| 1346 Comment cmnt(masm_, "[ WithEnterStatement"); | 1384 Comment cmnt(masm_, "[ WithEnterStatement"); |
| 1347 CodeForStatementPosition(node); | 1385 CodeForStatementPosition(node); |
| 1348 LoadAndSpill(node->expression()); | 1386 LoadAndSpill(node->expression()); |
| 1349 if (node->is_catch_block()) { | 1387 if (node->is_catch_block()) { |
| 1350 frame_->CallRuntime(Runtime::kPushCatchContext, 1); | 1388 frame_->CallRuntime(Runtime::kPushCatchContext, 1); |
| 1351 } else { | 1389 } else { |
| 1352 frame_->CallRuntime(Runtime::kPushContext, 1); | 1390 frame_->CallRuntime(Runtime::kPushContext, 1); |
| 1353 } | 1391 } |
| 1354 if (kDebug) { | 1392 if (kDebug) { |
| 1355 JumpTarget verified_true(this); | 1393 JumpTarget verified_true(this); |
| 1356 __ cmp(r0, Operand(cp)); | 1394 __ cmp(r0, Operand(cp)); |
| 1357 verified_true.Branch(eq); | 1395 verified_true.Branch(eq); |
| 1358 __ stop("PushContext: r0 is expected to be the same as cp"); | 1396 __ stop("PushContext: r0 is expected to be the same as cp"); |
| 1359 verified_true.Bind(); | 1397 verified_true.Bind(); |
| 1360 } | 1398 } |
| 1361 // Update context local. | 1399 // Update context local. |
| 1362 __ str(cp, frame_->Context()); | 1400 __ str(cp, frame_->Context()); |
| 1401 ASSERT(frame_->height() == original_height); | |
| 1363 } | 1402 } |
| 1364 | 1403 |
| 1365 | 1404 |
| 1366 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 1405 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
| 1406 #ifdef DEBUG | |
| 1407 int original_height = frame_->height(); | |
| 1408 #endif | |
| 1367 VirtualFrame::SpilledScope spilled_scope(this); | 1409 VirtualFrame::SpilledScope spilled_scope(this); |
| 1368 Comment cmnt(masm_, "[ WithExitStatement"); | 1410 Comment cmnt(masm_, "[ WithExitStatement"); |
| 1369 CodeForStatementPosition(node); | 1411 CodeForStatementPosition(node); |
| 1370 // Pop context. | 1412 // Pop context. |
| 1371 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); | 1413 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); |
| 1372 // Update context local. | 1414 // Update context local. |
| 1373 __ str(cp, frame_->Context()); | 1415 __ str(cp, frame_->Context()); |
| 1416 ASSERT(frame_->height() == original_height); | |
| 1374 } | 1417 } |
| 1375 | 1418 |
| 1376 | 1419 |
| 1377 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 1420 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { |
| 1378 return kFastSwitchMaxOverheadFactor; | 1421 return kFastSwitchMaxOverheadFactor; |
| 1379 } | 1422 } |
| 1380 | 1423 |
| 1381 int CodeGenerator::FastCaseSwitchMinCaseCount() { | 1424 int CodeGenerator::FastCaseSwitchMinCaseCount() { |
| 1382 return kFastSwitchMinCaseCount; | 1425 return kFastSwitchMinCaseCount; |
| 1383 } | 1426 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1431 // Table containing branch operations. | 1474 // Table containing branch operations. |
| 1432 for (int i = 0; i < range; i++) { | 1475 for (int i = 0; i < range; i++) { |
| 1433 __ jmp(case_targets[i]); | 1476 __ jmp(case_targets[i]); |
| 1434 } | 1477 } |
| 1435 GenerateFastCaseSwitchCases(node, case_labels, start_frame); | 1478 GenerateFastCaseSwitchCases(node, case_labels, start_frame); |
| 1436 delete start_frame; | 1479 delete start_frame; |
| 1437 } | 1480 } |
| 1438 | 1481 |
| 1439 | 1482 |
| 1440 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 1483 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
| 1484 #ifdef DEBUG | |
| 1485 int original_height = frame_->height(); | |
| 1486 #endif | |
| 1441 VirtualFrame::SpilledScope spilled_scope(this); | 1487 VirtualFrame::SpilledScope spilled_scope(this); |
| 1442 Comment cmnt(masm_, "[ SwitchStatement"); | 1488 Comment cmnt(masm_, "[ SwitchStatement"); |
| 1443 CodeForStatementPosition(node); | 1489 CodeForStatementPosition(node); |
| 1444 node->set_break_stack_height(break_stack_height_); | 1490 node->set_break_stack_height(break_stack_height_); |
| 1445 node->break_target()->Initialize(this); | 1491 node->break_target()->Initialize(this); |
| 1446 | 1492 |
| 1447 LoadAndSpill(node->tag()); | 1493 LoadAndSpill(node->tag()); |
| 1448 if (TryGenerateFastCaseSwitchStatement(node)) { | 1494 if (TryGenerateFastCaseSwitchStatement(node)) { |
| 1495 ASSERT(frame_->height() == original_height); | |
| 1449 return; | 1496 return; |
| 1450 } | 1497 } |
| 1451 | 1498 |
| 1452 JumpTarget next_test(this); | 1499 JumpTarget next_test(this); |
| 1453 JumpTarget fall_through(this); | 1500 JumpTarget fall_through(this); |
| 1454 JumpTarget default_entry(this); | 1501 JumpTarget default_entry(this); |
| 1455 JumpTarget default_exit(this); | 1502 JumpTarget default_exit(this); |
| 1456 ZoneList<CaseClause*>* cases = node->cases(); | 1503 ZoneList<CaseClause*>* cases = node->cases(); |
| 1457 int length = cases->length(); | 1504 int length = cases->length(); |
| 1458 CaseClause* default_clause = NULL; | 1505 CaseClause* default_clause = NULL; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1516 } | 1563 } |
| 1517 } | 1564 } |
| 1518 | 1565 |
| 1519 if (fall_through.is_linked()) { | 1566 if (fall_through.is_linked()) { |
| 1520 fall_through.Bind(); | 1567 fall_through.Bind(); |
| 1521 } | 1568 } |
| 1522 | 1569 |
| 1523 if (node->break_target()->is_linked()) { | 1570 if (node->break_target()->is_linked()) { |
| 1524 node->break_target()->Bind(); | 1571 node->break_target()->Bind(); |
| 1525 } | 1572 } |
| 1573 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
|
William Hesse
2009/02/20 13:06:20
How could there not be a valid frame here, if the
Kevin Millikin (Chromium)
2009/02/20 13:12:48
If the last case we compile returns and none of th
| |
| 1526 } | 1574 } |
| 1527 | 1575 |
| 1528 | 1576 |
| 1529 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1577 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { |
| 1578 #ifdef DEBUG | |
| 1579 int original_height = frame_->height(); | |
| 1580 #endif | |
| 1530 VirtualFrame::SpilledScope spilled_scope(this); | 1581 VirtualFrame::SpilledScope spilled_scope(this); |
| 1531 Comment cmnt(masm_, "[ LoopStatement"); | 1582 Comment cmnt(masm_, "[ LoopStatement"); |
| 1532 CodeForStatementPosition(node); | 1583 CodeForStatementPosition(node); |
| 1533 node->set_break_stack_height(break_stack_height_); | 1584 node->set_break_stack_height(break_stack_height_); |
| 1534 node->break_target()->Initialize(this); | 1585 node->break_target()->Initialize(this); |
| 1535 | 1586 |
| 1536 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a | 1587 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a |
| 1537 // known result for the test expression, with no side effects. | 1588 // known result for the test expression, with no side effects. |
| 1538 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1589 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; |
| 1539 if (node->cond() == NULL) { | 1590 if (node->cond() == NULL) { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1700 } | 1751 } |
| 1701 } | 1752 } |
| 1702 } | 1753 } |
| 1703 break; | 1754 break; |
| 1704 } | 1755 } |
| 1705 } | 1756 } |
| 1706 | 1757 |
| 1707 if (node->break_target()->is_linked()) { | 1758 if (node->break_target()->is_linked()) { |
| 1708 node->break_target()->Bind(); | 1759 node->break_target()->Bind(); |
| 1709 } | 1760 } |
| 1761 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
| 1710 } | 1762 } |
| 1711 | 1763 |
| 1712 | 1764 |
| 1713 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 1765 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
| 1766 #ifdef DEBUG | |
| 1767 int original_height = frame_->height(); | |
| 1768 #endif | |
| 1714 ASSERT(!in_spilled_code()); | 1769 ASSERT(!in_spilled_code()); |
| 1715 VirtualFrame::SpilledScope spilled_scope(this); | 1770 VirtualFrame::SpilledScope spilled_scope(this); |
| 1716 Comment cmnt(masm_, "[ ForInStatement"); | 1771 Comment cmnt(masm_, "[ ForInStatement"); |
| 1717 CodeForStatementPosition(node); | 1772 CodeForStatementPosition(node); |
| 1718 | 1773 |
| 1719 // We keep stuff on the stack while the body is executing. | 1774 // We keep stuff on the stack while the body is executing. |
| 1720 // Record it, so that a break/continue crossing this statement | 1775 // Record it, so that a break/continue crossing this statement |
| 1721 // can restore the stack. | 1776 // can restore the stack. |
| 1722 const int kForInStackSize = 5 * kPointerSize; | 1777 const int kForInStackSize = 5 * kPointerSize; |
| 1723 break_stack_height_ += kForInStackSize; | 1778 break_stack_height_ += kForInStackSize; |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1897 entry.Jump(); | 1952 entry.Jump(); |
| 1898 | 1953 |
| 1899 // Cleanup. | 1954 // Cleanup. |
| 1900 node->break_target()->Bind(); | 1955 node->break_target()->Bind(); |
| 1901 frame_->Drop(5); | 1956 frame_->Drop(5); |
| 1902 | 1957 |
| 1903 // Exit. | 1958 // Exit. |
| 1904 exit.Bind(); | 1959 exit.Bind(); |
| 1905 | 1960 |
| 1906 break_stack_height_ -= kForInStackSize; | 1961 break_stack_height_ -= kForInStackSize; |
| 1962 ASSERT(frame_->height() == original_height); | |
| 1907 } | 1963 } |
| 1908 | 1964 |
| 1909 | 1965 |
| 1910 void CodeGenerator::VisitTryCatch(TryCatch* node) { | 1966 void CodeGenerator::VisitTryCatch(TryCatch* node) { |
| 1967 #ifdef DEBUG | |
| 1968 int original_height = frame_->height(); | |
| 1969 #endif | |
| 1911 VirtualFrame::SpilledScope spilled_scope(this); | 1970 VirtualFrame::SpilledScope spilled_scope(this); |
| 1912 Comment cmnt(masm_, "[ TryCatch"); | 1971 Comment cmnt(masm_, "[ TryCatch"); |
| 1913 CodeForStatementPosition(node); | 1972 CodeForStatementPosition(node); |
| 1914 | 1973 |
| 1915 JumpTarget try_block(this); | 1974 JumpTarget try_block(this); |
| 1916 JumpTarget exit(this); | 1975 JumpTarget exit(this); |
| 1917 | 1976 |
| 1918 try_block.Call(); | 1977 try_block.Call(); |
| 1919 // --- Catch block --- | 1978 // --- Catch block --- |
| 1920 frame_->EmitPush(r0); | 1979 frame_->EmitPush(r0); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2008 __ str(r1, MemOperand(r3)); | 2067 __ str(r1, MemOperand(r3)); |
| 2009 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 2068 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
| 2010 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2069 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
| 2011 // Code slot popped. | 2070 // Code slot popped. |
| 2012 frame_->Forget(1); | 2071 frame_->Forget(1); |
| 2013 shadows[i]->other_target()->Jump(); | 2072 shadows[i]->other_target()->Jump(); |
| 2014 } | 2073 } |
| 2015 } | 2074 } |
| 2016 | 2075 |
| 2017 exit.Bind(); | 2076 exit.Bind(); |
| 2077 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
| 2018 } | 2078 } |
| 2019 | 2079 |
| 2020 | 2080 |
| 2021 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 2081 void CodeGenerator::VisitTryFinally(TryFinally* node) { |
| 2082 #ifdef DEBUG | |
| 2083 int original_height = frame_->height(); | |
| 2084 #endif | |
| 2022 VirtualFrame::SpilledScope spilled_scope(this); | 2085 VirtualFrame::SpilledScope spilled_scope(this); |
| 2023 Comment cmnt(masm_, "[ TryFinally"); | 2086 Comment cmnt(masm_, "[ TryFinally"); |
| 2024 CodeForStatementPosition(node); | 2087 CodeForStatementPosition(node); |
| 2025 | 2088 |
| 2026 // State: Used to keep track of reason for entering the finally | 2089 // State: Used to keep track of reason for entering the finally |
| 2027 // block. Should probably be extended to hold information for | 2090 // block. Should probably be extended to hold information for |
| 2028 // break/continue from within the try block. | 2091 // break/continue from within the try block. |
| 2029 enum { FALLING, THROWING, JUMPING }; | 2092 enum { FALLING, THROWING, JUMPING }; |
| 2030 | 2093 |
| 2031 JumpTarget unlink(this); | 2094 JumpTarget unlink(this); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2167 __ cmp(r2, Operand(Smi::FromInt(THROWING))); | 2230 __ cmp(r2, Operand(Smi::FromInt(THROWING))); |
| 2168 exit.Branch(ne); | 2231 exit.Branch(ne); |
| 2169 | 2232 |
| 2170 // Rethrow exception. | 2233 // Rethrow exception. |
| 2171 frame_->EmitPush(r0); | 2234 frame_->EmitPush(r0); |
| 2172 frame_->CallRuntime(Runtime::kReThrow, 1); | 2235 frame_->CallRuntime(Runtime::kReThrow, 1); |
| 2173 | 2236 |
| 2174 // Done. | 2237 // Done. |
| 2175 exit.Bind(); | 2238 exit.Bind(); |
| 2176 } | 2239 } |
| 2240 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
| 2177 } | 2241 } |
| 2178 | 2242 |
| 2179 | 2243 |
| 2180 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 2244 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
| 2245 #ifdef DEBUG | |
| 2246 int original_height = frame_->height(); | |
| 2247 #endif | |
| 2181 VirtualFrame::SpilledScope spilled_scope(this); | 2248 VirtualFrame::SpilledScope spilled_scope(this); |
| 2182 Comment cmnt(masm_, "[ DebuggerStatament"); | 2249 Comment cmnt(masm_, "[ DebuggerStatament"); |
| 2183 CodeForStatementPosition(node); | 2250 CodeForStatementPosition(node); |
| 2184 frame_->CallRuntime(Runtime::kDebugBreak, 0); | 2251 frame_->CallRuntime(Runtime::kDebugBreak, 0); |
| 2185 // Ignore the return value. | 2252 // Ignore the return value. |
| 2253 ASSERT(frame_->height() == original_height); | |
| 2186 } | 2254 } |
| 2187 | 2255 |
| 2188 | 2256 |
| 2189 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 2257 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { |
| 2190 VirtualFrame::SpilledScope spilled_scope(this); | 2258 VirtualFrame::SpilledScope spilled_scope(this); |
| 2191 ASSERT(boilerplate->IsBoilerplate()); | 2259 ASSERT(boilerplate->IsBoilerplate()); |
| 2192 | 2260 |
| 2193 // Push the boilerplate on the stack. | 2261 // Push the boilerplate on the stack. |
| 2194 __ mov(r0, Operand(boilerplate)); | 2262 __ mov(r0, Operand(boilerplate)); |
| 2195 frame_->EmitPush(r0); | 2263 frame_->EmitPush(r0); |
| 2196 | 2264 |
| 2197 // Create a new closure. | 2265 // Create a new closure. |
| 2198 frame_->EmitPush(cp); | 2266 frame_->EmitPush(cp); |
| 2199 frame_->CallRuntime(Runtime::kNewClosure, 2); | 2267 frame_->CallRuntime(Runtime::kNewClosure, 2); |
| 2200 frame_->EmitPush(r0); | 2268 frame_->EmitPush(r0); |
| 2201 } | 2269 } |
| 2202 | 2270 |
| 2203 | 2271 |
| 2204 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 2272 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
| 2273 #ifdef DEBUG | |
| 2274 int original_height = frame_->height(); | |
| 2275 #endif | |
| 2205 VirtualFrame::SpilledScope spilled_scope(this); | 2276 VirtualFrame::SpilledScope spilled_scope(this); |
| 2206 Comment cmnt(masm_, "[ FunctionLiteral"); | 2277 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 2207 | 2278 |
| 2208 // Build the function boilerplate and instantiate it. | 2279 // Build the function boilerplate and instantiate it. |
| 2209 Handle<JSFunction> boilerplate = BuildBoilerplate(node); | 2280 Handle<JSFunction> boilerplate = BuildBoilerplate(node); |
| 2210 // Check for stack-overflow exception. | 2281 // Check for stack-overflow exception. |
| 2211 if (HasStackOverflow()) return; | 2282 if (HasStackOverflow()) { |
| 2283 ASSERT(frame_->height() == original_height); | |
| 2284 return; | |
| 2285 } | |
| 2212 InstantiateBoilerplate(boilerplate); | 2286 InstantiateBoilerplate(boilerplate); |
| 2287 ASSERT(frame_->height() == original_height + 1); | |
| 2213 } | 2288 } |
| 2214 | 2289 |
| 2215 | 2290 |
| 2216 void CodeGenerator::VisitFunctionBoilerplateLiteral( | 2291 void CodeGenerator::VisitFunctionBoilerplateLiteral( |
| 2217 FunctionBoilerplateLiteral* node) { | 2292 FunctionBoilerplateLiteral* node) { |
| 2293 #ifdef DEBUG | |
| 2294 int original_height = frame_->height(); | |
| 2295 #endif | |
| 2218 VirtualFrame::SpilledScope spilled_scope(this); | 2296 VirtualFrame::SpilledScope spilled_scope(this); |
| 2219 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); | 2297 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); |
| 2220 InstantiateBoilerplate(node->boilerplate()); | 2298 InstantiateBoilerplate(node->boilerplate()); |
| 2299 ASSERT(frame_->height() == original_height + 1); | |
| 2221 } | 2300 } |
| 2222 | 2301 |
| 2223 | 2302 |
| 2224 void CodeGenerator::VisitConditional(Conditional* node) { | 2303 void CodeGenerator::VisitConditional(Conditional* node) { |
| 2304 #ifdef DEBUG | |
| 2305 int original_height = frame_->height(); | |
| 2306 #endif | |
| 2225 VirtualFrame::SpilledScope spilled_scope(this); | 2307 VirtualFrame::SpilledScope spilled_scope(this); |
| 2226 Comment cmnt(masm_, "[ Conditional"); | 2308 Comment cmnt(masm_, "[ Conditional"); |
| 2227 JumpTarget then(this); | 2309 JumpTarget then(this); |
| 2228 JumpTarget else_(this); | 2310 JumpTarget else_(this); |
| 2229 JumpTarget exit(this); | 2311 JumpTarget exit(this); |
| 2230 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, | 2312 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, |
| 2231 &then, &else_, true); | 2313 &then, &else_, true); |
| 2232 Branch(false, &else_); | 2314 Branch(false, &else_); |
| 2233 then.Bind(); | 2315 then.Bind(); |
| 2234 LoadAndSpill(node->then_expression(), typeof_state()); | 2316 LoadAndSpill(node->then_expression(), typeof_state()); |
| 2235 exit.Jump(); | 2317 exit.Jump(); |
| 2236 else_.Bind(); | 2318 else_.Bind(); |
| 2237 LoadAndSpill(node->else_expression(), typeof_state()); | 2319 LoadAndSpill(node->else_expression(), typeof_state()); |
| 2238 exit.Bind(); | 2320 exit.Bind(); |
| 2321 ASSERT(frame_->height() == original_height + 1); | |
| 2239 } | 2322 } |
| 2240 | 2323 |
| 2241 | 2324 |
| 2242 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 2325 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
| 2243 VirtualFrame::SpilledScope spilled_scope(this); | 2326 VirtualFrame::SpilledScope spilled_scope(this); |
| 2244 if (slot->type() == Slot::LOOKUP) { | 2327 if (slot->type() == Slot::LOOKUP) { |
| 2245 ASSERT(slot->var()->is_dynamic()); | 2328 ASSERT(slot->var()->is_dynamic()); |
| 2246 | 2329 |
| 2247 JumpTarget slow(this); | 2330 JumpTarget slow(this); |
| 2248 JumpTarget done(this); | 2331 JumpTarget done(this); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2351 } else { | 2434 } else { |
| 2352 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, &name, 0); | 2435 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, &name, 0); |
| 2353 } | 2436 } |
| 2354 | 2437 |
| 2355 // Drop the global object. The result is in r0. | 2438 // Drop the global object. The result is in r0. |
| 2356 frame_->Drop(); | 2439 frame_->Drop(); |
| 2357 } | 2440 } |
| 2358 | 2441 |
| 2359 | 2442 |
| 2360 void CodeGenerator::VisitSlot(Slot* node) { | 2443 void CodeGenerator::VisitSlot(Slot* node) { |
| 2444 #ifdef DEBUG | |
| 2445 int original_height = frame_->height(); | |
| 2446 #endif | |
| 2361 VirtualFrame::SpilledScope spilled_scope(this); | 2447 VirtualFrame::SpilledScope spilled_scope(this); |
| 2362 Comment cmnt(masm_, "[ Slot"); | 2448 Comment cmnt(masm_, "[ Slot"); |
| 2363 LoadFromSlot(node, typeof_state()); | 2449 LoadFromSlot(node, typeof_state()); |
| 2450 ASSERT(frame_->height() == original_height + 1); | |
| 2364 } | 2451 } |
| 2365 | 2452 |
| 2366 | 2453 |
| 2367 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { | 2454 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { |
| 2455 #ifdef DEBUG | |
| 2456 int original_height = frame_->height(); | |
| 2457 #endif | |
| 2368 VirtualFrame::SpilledScope spilled_scope(this); | 2458 VirtualFrame::SpilledScope spilled_scope(this); |
| 2369 Comment cmnt(masm_, "[ VariableProxy"); | 2459 Comment cmnt(masm_, "[ VariableProxy"); |
| 2370 | 2460 |
| 2371 Variable* var = node->var(); | 2461 Variable* var = node->var(); |
| 2372 Expression* expr = var->rewrite(); | 2462 Expression* expr = var->rewrite(); |
| 2373 if (expr != NULL) { | 2463 if (expr != NULL) { |
| 2374 Visit(expr); | 2464 Visit(expr); |
| 2375 } else { | 2465 } else { |
| 2376 ASSERT(var->is_global()); | 2466 ASSERT(var->is_global()); |
| 2377 Reference ref(this, node); | 2467 Reference ref(this, node); |
| 2378 ref.GetValueAndSpill(typeof_state()); | 2468 ref.GetValueAndSpill(typeof_state()); |
| 2379 } | 2469 } |
| 2470 ASSERT(frame_->height() == original_height + 1); | |
| 2380 } | 2471 } |
| 2381 | 2472 |
| 2382 | 2473 |
| 2383 void CodeGenerator::VisitLiteral(Literal* node) { | 2474 void CodeGenerator::VisitLiteral(Literal* node) { |
| 2475 #ifdef DEBUG | |
| 2476 int original_height = frame_->height(); | |
| 2477 #endif | |
| 2384 VirtualFrame::SpilledScope spilled_scope(this); | 2478 VirtualFrame::SpilledScope spilled_scope(this); |
| 2385 Comment cmnt(masm_, "[ Literal"); | 2479 Comment cmnt(masm_, "[ Literal"); |
| 2386 __ mov(r0, Operand(node->handle())); | 2480 __ mov(r0, Operand(node->handle())); |
| 2387 frame_->EmitPush(r0); | 2481 frame_->EmitPush(r0); |
| 2482 ASSERT(frame_->height() == original_height + 1); | |
| 2388 } | 2483 } |
| 2389 | 2484 |
| 2390 | 2485 |
| 2391 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 2486 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
| 2487 #ifdef DEBUG | |
| 2488 int original_height = frame_->height(); | |
| 2489 #endif | |
| 2392 VirtualFrame::SpilledScope spilled_scope(this); | 2490 VirtualFrame::SpilledScope spilled_scope(this); |
| 2393 Comment cmnt(masm_, "[ RexExp Literal"); | 2491 Comment cmnt(masm_, "[ RexExp Literal"); |
| 2394 | 2492 |
| 2395 // Retrieve the literal array and check the allocated entry. | 2493 // Retrieve the literal array and check the allocated entry. |
| 2396 | 2494 |
| 2397 // Load the function of this activation. | 2495 // Load the function of this activation. |
| 2398 __ ldr(r1, frame_->Function()); | 2496 __ ldr(r1, frame_->Function()); |
| 2399 | 2497 |
| 2400 // Load the literals array of the function. | 2498 // Load the literals array of the function. |
| 2401 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); | 2499 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2417 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2) | 2515 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2) |
| 2418 frame_->EmitPush(r0); | 2516 frame_->EmitPush(r0); |
| 2419 __ mov(r0, Operand(node->flags())); // RegExp flags (3) | 2517 __ mov(r0, Operand(node->flags())); // RegExp flags (3) |
| 2420 frame_->EmitPush(r0); | 2518 frame_->EmitPush(r0); |
| 2421 frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 2519 frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 2422 __ mov(r2, Operand(r0)); | 2520 __ mov(r2, Operand(r0)); |
| 2423 | 2521 |
| 2424 done.Bind(); | 2522 done.Bind(); |
| 2425 // Push the literal. | 2523 // Push the literal. |
| 2426 frame_->EmitPush(r2); | 2524 frame_->EmitPush(r2); |
| 2525 ASSERT(frame_->height() == original_height + 1); | |
| 2427 } | 2526 } |
| 2428 | 2527 |
| 2429 | 2528 |
| 2430 // This deferred code stub will be used for creating the boilerplate | 2529 // This deferred code stub will be used for creating the boilerplate |
| 2431 // by calling Runtime_CreateObjectLiteral. | 2530 // by calling Runtime_CreateObjectLiteral. |
| 2432 // Each created boilerplate is stored in the JSFunction and they are | 2531 // Each created boilerplate is stored in the JSFunction and they are |
| 2433 // therefore context dependent. | 2532 // therefore context dependent. |
| 2434 class DeferredObjectLiteral: public DeferredCode { | 2533 class DeferredObjectLiteral: public DeferredCode { |
| 2435 public: | 2534 public: |
| 2436 DeferredObjectLiteral(CodeGenerator* generator, ObjectLiteral* node) | 2535 DeferredObjectLiteral(CodeGenerator* generator, ObjectLiteral* node) |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2464 frame->EmitPush(r0); | 2563 frame->EmitPush(r0); |
| 2465 Result boilerplate = | 2564 Result boilerplate = |
| 2466 frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); | 2565 frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); |
| 2467 __ mov(r2, Operand(boilerplate.reg())); | 2566 __ mov(r2, Operand(boilerplate.reg())); |
| 2468 // Result is returned in r2. | 2567 // Result is returned in r2. |
| 2469 exit_.Jump(); | 2568 exit_.Jump(); |
| 2470 } | 2569 } |
| 2471 | 2570 |
| 2472 | 2571 |
| 2473 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 2572 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
| 2573 #ifdef DEBUG | |
| 2574 int original_height = frame_->height(); | |
| 2575 #endif | |
| 2474 VirtualFrame::SpilledScope spilled_scope(this); | 2576 VirtualFrame::SpilledScope spilled_scope(this); |
| 2475 Comment cmnt(masm_, "[ ObjectLiteral"); | 2577 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 2476 | 2578 |
| 2477 DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node); | 2579 DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node); |
| 2478 | 2580 |
| 2479 // Retrieve the literal array and check the allocated entry. | 2581 // Retrieve the literal array and check the allocated entry. |
| 2480 | 2582 |
| 2481 // Load the function of this activation. | 2583 // Load the function of this activation. |
| 2482 __ ldr(r1, frame_->Function()); | 2584 __ ldr(r1, frame_->Function()); |
| 2483 | 2585 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2534 LoadAndSpill(key); | 2636 LoadAndSpill(key); |
| 2535 __ mov(r0, Operand(Smi::FromInt(0))); | 2637 __ mov(r0, Operand(Smi::FromInt(0))); |
| 2536 frame_->EmitPush(r0); | 2638 frame_->EmitPush(r0); |
| 2537 LoadAndSpill(value); | 2639 LoadAndSpill(value); |
| 2538 frame_->CallRuntime(Runtime::kDefineAccessor, 4); | 2640 frame_->CallRuntime(Runtime::kDefineAccessor, 4); |
| 2539 __ ldr(r0, frame_->Top()); | 2641 __ ldr(r0, frame_->Top()); |
| 2540 break; | 2642 break; |
| 2541 } | 2643 } |
| 2542 } | 2644 } |
| 2543 } | 2645 } |
| 2646 ASSERT(frame_->height() == original_height + 1); | |
| 2544 } | 2647 } |
| 2545 | 2648 |
| 2546 | 2649 |
| 2547 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 2650 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
| 2651 #ifdef DEBUG | |
| 2652 int original_height = frame_->height(); | |
| 2653 #endif | |
| 2548 VirtualFrame::SpilledScope spilled_scope(this); | 2654 VirtualFrame::SpilledScope spilled_scope(this); |
| 2549 Comment cmnt(masm_, "[ ArrayLiteral"); | 2655 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 2550 | 2656 |
| 2551 // Call runtime to create the array literal. | 2657 // Call runtime to create the array literal. |
| 2552 __ mov(r0, Operand(node->literals())); | 2658 __ mov(r0, Operand(node->literals())); |
| 2553 frame_->EmitPush(r0); | 2659 frame_->EmitPush(r0); |
| 2554 // Load the function of this frame. | 2660 // Load the function of this frame. |
| 2555 __ ldr(r0, frame_->Function()); | 2661 __ ldr(r0, frame_->Function()); |
| 2556 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 2662 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
| 2557 frame_->EmitPush(r0); | 2663 frame_->EmitPush(r0); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2579 | 2685 |
| 2580 // Write to the indexed properties array. | 2686 // Write to the indexed properties array. |
| 2581 int offset = i * kPointerSize + Array::kHeaderSize; | 2687 int offset = i * kPointerSize + Array::kHeaderSize; |
| 2582 __ str(r0, FieldMemOperand(r1, offset)); | 2688 __ str(r0, FieldMemOperand(r1, offset)); |
| 2583 | 2689 |
| 2584 // Update the write barrier for the array address. | 2690 // Update the write barrier for the array address. |
| 2585 __ mov(r3, Operand(offset)); | 2691 __ mov(r3, Operand(offset)); |
| 2586 __ RecordWrite(r1, r3, r2); | 2692 __ RecordWrite(r1, r3, r2); |
| 2587 } | 2693 } |
| 2588 } | 2694 } |
| 2695 ASSERT(frame_->height() == original_height + 1); | |
| 2589 } | 2696 } |
| 2590 | 2697 |
| 2591 | 2698 |
| 2592 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { | 2699 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
| 2700 #ifdef DEBUG | |
| 2701 int original_height = frame_->height(); | |
| 2702 #endif | |
| 2593 ASSERT(!in_spilled_code()); | 2703 ASSERT(!in_spilled_code()); |
| 2594 VirtualFrame::SpilledScope spilled_scope(this); | 2704 VirtualFrame::SpilledScope spilled_scope(this); |
| 2595 // Call runtime routine to allocate the catch extension object and | 2705 // Call runtime routine to allocate the catch extension object and |
| 2596 // assign the exception value to the catch variable. | 2706 // assign the exception value to the catch variable. |
| 2597 Comment cmnt(masm_, "[ CatchExtensionObject"); | 2707 Comment cmnt(masm_, "[ CatchExtensionObject"); |
| 2598 LoadAndSpill(node->key()); | 2708 LoadAndSpill(node->key()); |
| 2599 LoadAndSpill(node->value()); | 2709 LoadAndSpill(node->value()); |
| 2600 Result result = | 2710 Result result = |
| 2601 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 2711 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
| 2602 frame_->EmitPush(result.reg()); | 2712 frame_->EmitPush(result.reg()); |
| 2713 ASSERT(frame_->height() == original_height + 1); | |
| 2603 } | 2714 } |
| 2604 | 2715 |
| 2605 | 2716 |
| 2606 void CodeGenerator::VisitAssignment(Assignment* node) { | 2717 void CodeGenerator::VisitAssignment(Assignment* node) { |
| 2718 #ifdef DEBUG | |
| 2719 int original_height = frame_->height(); | |
| 2720 #endif | |
| 2607 VirtualFrame::SpilledScope spilled_scope(this); | 2721 VirtualFrame::SpilledScope spilled_scope(this); |
| 2608 Comment cmnt(masm_, "[ Assignment"); | 2722 Comment cmnt(masm_, "[ Assignment"); |
| 2609 CodeForStatementPosition(node); | 2723 CodeForStatementPosition(node); |
| 2610 | 2724 |
| 2611 Reference target(this, node->target()); | 2725 { Reference target(this, node->target()); |
| 2612 if (target.is_illegal()) { | 2726 if (target.is_illegal()) { |
| 2613 // Fool the virtual frame into thinking that we left the assignment's | 2727 // Fool the virtual frame into thinking that we left the assignment's |
| 2614 // value on the frame. | 2728 // value on the frame. |
| 2615 __ mov(r0, Operand(Smi::FromInt(0))); | 2729 __ mov(r0, Operand(Smi::FromInt(0))); |
| 2616 frame_->EmitPush(r0); | 2730 frame_->EmitPush(r0); |
| 2617 return; | 2731 ASSERT(frame_->height() == original_height + 1); |
| 2618 } | 2732 return; |
| 2733 } | |
| 2619 | 2734 |
| 2620 if (node->op() == Token::ASSIGN || | 2735 if (node->op() == Token::ASSIGN || |
| 2621 node->op() == Token::INIT_VAR || | 2736 node->op() == Token::INIT_VAR || |
| 2622 node->op() == Token::INIT_CONST) { | 2737 node->op() == Token::INIT_CONST) { |
| 2623 LoadAndSpill(node->value()); | 2738 LoadAndSpill(node->value()); |
| 2624 | |
| 2625 } else { | |
| 2626 target.GetValueAndSpill(NOT_INSIDE_TYPEOF); | |
| 2627 Literal* literal = node->value()->AsLiteral(); | |
| 2628 if (literal != NULL && literal->handle()->IsSmi()) { | |
| 2629 SmiOperation(node->binary_op(), literal->handle(), false); | |
| 2630 frame_->EmitPush(r0); | |
| 2631 | 2739 |
| 2632 } else { | 2740 } else { |
| 2633 LoadAndSpill(node->value()); | 2741 target.GetValueAndSpill(NOT_INSIDE_TYPEOF); |
| 2634 GenericBinaryOperation(node->binary_op()); | 2742 Literal* literal = node->value()->AsLiteral(); |
| 2635 frame_->EmitPush(r0); | 2743 if (literal != NULL && literal->handle()->IsSmi()) { |
| 2744 SmiOperation(node->binary_op(), literal->handle(), false); | |
| 2745 frame_->EmitPush(r0); | |
| 2746 | |
| 2747 } else { | |
| 2748 LoadAndSpill(node->value()); | |
| 2749 GenericBinaryOperation(node->binary_op()); | |
| 2750 frame_->EmitPush(r0); | |
| 2751 } | |
| 2752 } | |
| 2753 | |
| 2754 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | |
| 2755 if (var != NULL && | |
| 2756 (var->mode() == Variable::CONST) && | |
| 2757 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { | |
| 2758 // Assignment ignored - leave the value on the stack. | |
| 2759 | |
| 2760 } else { | |
| 2761 CodeForSourcePosition(node->position()); | |
| 2762 if (node->op() == Token::INIT_CONST) { | |
| 2763 // Dynamic constant initializations must use the function context | |
| 2764 // and initialize the actual constant declared. Dynamic variable | |
| 2765 // initializations are simply assignments and use SetValue. | |
| 2766 target.SetValue(CONST_INIT); | |
| 2767 } else { | |
| 2768 target.SetValue(NOT_CONST_INIT); | |
| 2769 } | |
| 2636 } | 2770 } |
| 2637 } | 2771 } |
| 2638 | 2772 ASSERT(frame_->height() == original_height + 1); |
| 2639 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | |
| 2640 if (var != NULL && | |
| 2641 (var->mode() == Variable::CONST) && | |
| 2642 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { | |
| 2643 // Assignment ignored - leave the value on the stack. | |
| 2644 | |
| 2645 } else { | |
| 2646 CodeForSourcePosition(node->position()); | |
| 2647 if (node->op() == Token::INIT_CONST) { | |
| 2648 // Dynamic constant initializations must use the function context | |
| 2649 // and initialize the actual constant declared. Dynamic variable | |
| 2650 // initializations are simply assignments and use SetValue. | |
| 2651 target.SetValue(CONST_INIT); | |
| 2652 } else { | |
| 2653 target.SetValue(NOT_CONST_INIT); | |
| 2654 } | |
| 2655 } | |
| 2656 } | 2773 } |
| 2657 | 2774 |
| 2658 | 2775 |
| 2659 void CodeGenerator::VisitThrow(Throw* node) { | 2776 void CodeGenerator::VisitThrow(Throw* node) { |
| 2777 #ifdef DEBUG | |
| 2778 int original_height = frame_->height(); | |
| 2779 #endif | |
| 2660 VirtualFrame::SpilledScope spilled_scope(this); | 2780 VirtualFrame::SpilledScope spilled_scope(this); |
| 2661 Comment cmnt(masm_, "[ Throw"); | 2781 Comment cmnt(masm_, "[ Throw"); |
| 2662 | 2782 |
| 2663 LoadAndSpill(node->exception()); | 2783 LoadAndSpill(node->exception()); |
| 2664 CodeForSourcePosition(node->position()); | 2784 CodeForSourcePosition(node->position()); |
| 2665 frame_->CallRuntime(Runtime::kThrow, 1); | 2785 frame_->CallRuntime(Runtime::kThrow, 1); |
| 2666 frame_->EmitPush(r0); | 2786 frame_->EmitPush(r0); |
| 2787 ASSERT(frame_->height() == original_height + 1); | |
| 2667 } | 2788 } |
| 2668 | 2789 |
| 2669 | 2790 |
| 2670 void CodeGenerator::VisitProperty(Property* node) { | 2791 void CodeGenerator::VisitProperty(Property* node) { |
| 2792 #ifdef DEBUG | |
| 2793 int original_height = frame_->height(); | |
| 2794 #endif | |
| 2671 VirtualFrame::SpilledScope spilled_scope(this); | 2795 VirtualFrame::SpilledScope spilled_scope(this); |
| 2672 Comment cmnt(masm_, "[ Property"); | 2796 Comment cmnt(masm_, "[ Property"); |
| 2673 | 2797 |
| 2674 Reference property(this, node); | 2798 { Reference property(this, node); |
| 2675 property.GetValueAndSpill(typeof_state()); | 2799 property.GetValueAndSpill(typeof_state()); |
| 2800 } | |
| 2801 ASSERT(frame_->height() == original_height + 1); | |
| 2676 } | 2802 } |
| 2677 | 2803 |
| 2678 | 2804 |
| 2679 void CodeGenerator::VisitCall(Call* node) { | 2805 void CodeGenerator::VisitCall(Call* node) { |
| 2806 #ifdef DEBUG | |
| 2807 int original_height = frame_->height(); | |
| 2808 #endif | |
| 2680 VirtualFrame::SpilledScope spilled_scope(this); | 2809 VirtualFrame::SpilledScope spilled_scope(this); |
| 2681 Comment cmnt(masm_, "[ Call"); | 2810 Comment cmnt(masm_, "[ Call"); |
| 2682 | 2811 |
| 2683 ZoneList<Expression*>* args = node->arguments(); | 2812 ZoneList<Expression*>* args = node->arguments(); |
| 2684 | 2813 |
| 2685 CodeForStatementPosition(node); | 2814 CodeForStatementPosition(node); |
| 2686 // Standard function call. | 2815 // Standard function call. |
| 2687 | 2816 |
| 2688 // Check if the function is a variable or a property. | 2817 // Check if the function is a variable or a property. |
| 2689 Expression* function = node->expression(); | 2818 Expression* function = node->expression(); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2806 // Load the function. | 2935 // Load the function. |
| 2807 LoadAndSpill(function); | 2936 LoadAndSpill(function); |
| 2808 | 2937 |
| 2809 // Pass the global proxy as the receiver. | 2938 // Pass the global proxy as the receiver. |
| 2810 LoadGlobalReceiver(r0); | 2939 LoadGlobalReceiver(r0); |
| 2811 | 2940 |
| 2812 // Call the function. | 2941 // Call the function. |
| 2813 CallWithArguments(args, node->position()); | 2942 CallWithArguments(args, node->position()); |
| 2814 frame_->EmitPush(r0); | 2943 frame_->EmitPush(r0); |
| 2815 } | 2944 } |
| 2945 ASSERT(frame_->height() == original_height + 1); | |
| 2816 } | 2946 } |
| 2817 | 2947 |
| 2818 | 2948 |
| 2819 void CodeGenerator::VisitCallEval(CallEval* node) { | 2949 void CodeGenerator::VisitCallEval(CallEval* node) { |
| 2950 #ifdef DEBUG | |
| 2951 int original_height = frame_->height(); | |
| 2952 #endif | |
| 2820 VirtualFrame::SpilledScope spilled_scope(this); | 2953 VirtualFrame::SpilledScope spilled_scope(this); |
| 2821 Comment cmnt(masm_, "[ CallEval"); | 2954 Comment cmnt(masm_, "[ CallEval"); |
| 2822 | 2955 |
| 2823 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve | 2956 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve |
| 2824 // the function we need to call and the receiver of the call. | 2957 // the function we need to call and the receiver of the call. |
| 2825 // Then we call the resolved function using the given arguments. | 2958 // Then we call the resolved function using the given arguments. |
| 2826 | 2959 |
| 2827 ZoneList<Expression*>* args = node->arguments(); | 2960 ZoneList<Expression*>* args = node->arguments(); |
| 2828 Expression* function = node->expression(); | 2961 Expression* function = node->expression(); |
| 2829 | 2962 |
| 2830 CodeForStatementPosition(node); | 2963 CodeForStatementPosition(node); |
| 2831 | 2964 |
| 2832 // Prepare stack for call to resolved function. | 2965 // Prepare stack for call to resolved function. |
| 2833 LoadAndSpill(function); | 2966 LoadAndSpill(function); |
| 2834 __ mov(r2, Operand(Factory::undefined_value())); | 2967 __ mov(r2, Operand(Factory::undefined_value())); |
| 2835 __ push(r2); // Slot for receiver | 2968 frame_->EmitPush(r2); // Slot for receiver |
| 2836 for (int i = 0; i < args->length(); i++) { | 2969 int arg_count = args->length(); |
| 2970 for (int i = 0; i < arg_count; i++) { | |
| 2837 LoadAndSpill(args->at(i)); | 2971 LoadAndSpill(args->at(i)); |
| 2838 } | 2972 } |
| 2839 | 2973 |
| 2840 // Prepare stack for call to ResolvePossiblyDirectEval. | 2974 // Prepare stack for call to ResolvePossiblyDirectEval. |
| 2841 __ ldr(r1, MemOperand(sp, args->length() * kPointerSize + kPointerSize)); | 2975 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize + kPointerSize)); |
| 2842 __ push(r1); | 2976 frame_->EmitPush(r1); |
| 2843 if (args->length() > 0) { | 2977 if (arg_count > 0) { |
| 2844 __ ldr(r1, MemOperand(sp, args->length() * kPointerSize)); | 2978 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 2845 __ push(r1); | 2979 frame_->EmitPush(r1); |
| 2846 } else { | 2980 } else { |
| 2847 __ push(r2); | 2981 frame_->EmitPush(r2); |
| 2848 } | 2982 } |
| 2849 | 2983 |
| 2850 // Resolve the call. | 2984 // Resolve the call. |
| 2851 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); | 2985 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); |
| 2852 | 2986 |
| 2853 // Touch up stack with the right values for the function and the receiver. | 2987 // Touch up stack with the right values for the function and the receiver. |
| 2854 __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize)); | 2988 __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize)); |
| 2855 __ str(r1, MemOperand(sp, (args->length() + 1) * kPointerSize)); | 2989 __ str(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2856 __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize + kPointerSize)); | 2990 __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize + kPointerSize)); |
| 2857 __ str(r1, MemOperand(sp, args->length() * kPointerSize)); | 2991 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 2858 | 2992 |
| 2859 // Call the function. | 2993 // Call the function. |
| 2860 CodeForSourcePosition(node->position()); | 2994 CodeForSourcePosition(node->position()); |
| 2861 | 2995 |
| 2862 CallFunctionStub call_function(args->length()); | 2996 CallFunctionStub call_function(arg_count); |
| 2863 __ CallStub(&call_function); | 2997 frame_->CallStub(&call_function, arg_count + 1); |
| 2864 | 2998 |
| 2865 __ ldr(cp, frame_->Context()); | 2999 __ ldr(cp, frame_->Context()); |
| 2866 // Remove the function from the stack. | 3000 // Remove the function from the stack. |
| 2867 frame_->Drop(); | 3001 frame_->Drop(); |
| 2868 frame_->EmitPush(r0); | 3002 frame_->EmitPush(r0); |
| 3003 ASSERT(frame_->height() == original_height + 1); | |
| 2869 } | 3004 } |
| 2870 | 3005 |
| 2871 | 3006 |
| 2872 void CodeGenerator::VisitCallNew(CallNew* node) { | 3007 void CodeGenerator::VisitCallNew(CallNew* node) { |
| 3008 #ifdef DEBUG | |
| 3009 int original_height = frame_->height(); | |
| 3010 #endif | |
| 2873 VirtualFrame::SpilledScope spilled_scope(this); | 3011 VirtualFrame::SpilledScope spilled_scope(this); |
| 2874 Comment cmnt(masm_, "[ CallNew"); | 3012 Comment cmnt(masm_, "[ CallNew"); |
| 2875 CodeForStatementPosition(node); | 3013 CodeForStatementPosition(node); |
| 2876 | 3014 |
| 2877 // According to ECMA-262, section 11.2.2, page 44, the function | 3015 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2878 // expression in new calls must be evaluated before the | 3016 // expression in new calls must be evaluated before the |
| 2879 // arguments. This is different from ordinary calls, where the | 3017 // arguments. This is different from ordinary calls, where the |
| 2880 // actual function to call is resolved after the arguments have been | 3018 // actual function to call is resolved after the arguments have been |
| 2881 // evaluated. | 3019 // evaluated. |
| 2882 | 3020 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2908 CodeForSourcePosition(node->position()); | 3046 CodeForSourcePosition(node->position()); |
| 2909 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 3047 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); |
| 2910 Result result = frame_->CallCodeObject(ic, | 3048 Result result = frame_->CallCodeObject(ic, |
| 2911 RelocInfo::CONSTRUCT_CALL, | 3049 RelocInfo::CONSTRUCT_CALL, |
| 2912 &num_args, | 3050 &num_args, |
| 2913 &function, | 3051 &function, |
| 2914 arg_count + 1); | 3052 arg_count + 1); |
| 2915 | 3053 |
| 2916 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). | 3054 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). |
| 2917 __ str(r0, frame_->Top()); | 3055 __ str(r0, frame_->Top()); |
| 3056 ASSERT(frame_->height() == original_height + 1); | |
| 2918 } | 3057 } |
| 2919 | 3058 |
| 2920 | 3059 |
| 2921 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 3060 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
| 2922 VirtualFrame::SpilledScope spilled_scope(this); | 3061 VirtualFrame::SpilledScope spilled_scope(this); |
| 2923 ASSERT(args->length() == 1); | 3062 ASSERT(args->length() == 1); |
| 2924 JumpTarget leave(this); | 3063 JumpTarget leave(this); |
| 2925 LoadAndSpill(args->at(0)); | 3064 LoadAndSpill(args->at(0)); |
| 2926 frame_->EmitPop(r0); // r0 contains object. | 3065 frame_->EmitPop(r0); // r0 contains object. |
| 2927 // if (object->IsSmi()) return the object. | 3066 // if (object->IsSmi()) return the object. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3077 LoadAndSpill(args->at(0)); | 3216 LoadAndSpill(args->at(0)); |
| 3078 LoadAndSpill(args->at(1)); | 3217 LoadAndSpill(args->at(1)); |
| 3079 frame_->EmitPop(r0); | 3218 frame_->EmitPop(r0); |
| 3080 frame_->EmitPop(r1); | 3219 frame_->EmitPop(r1); |
| 3081 __ cmp(r0, Operand(r1)); | 3220 __ cmp(r0, Operand(r1)); |
| 3082 cc_reg_ = eq; | 3221 cc_reg_ = eq; |
| 3083 } | 3222 } |
| 3084 | 3223 |
| 3085 | 3224 |
| 3086 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 3225 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
| 3226 #ifdef DEBUG | |
| 3227 int original_height = frame_->height(); | |
| 3228 #endif | |
| 3087 VirtualFrame::SpilledScope spilled_scope(this); | 3229 VirtualFrame::SpilledScope spilled_scope(this); |
| 3088 if (CheckForInlineRuntimeCall(node)) { | 3230 if (CheckForInlineRuntimeCall(node)) { |
| 3231 ASSERT((has_cc() && frame_->height() == original_height) || | |
| 3232 (!has_cc() && frame_->height() == original_height + 1)); | |
| 3089 return; | 3233 return; |
| 3090 } | 3234 } |
| 3091 | 3235 |
| 3092 ZoneList<Expression*>* args = node->arguments(); | 3236 ZoneList<Expression*>* args = node->arguments(); |
| 3093 Comment cmnt(masm_, "[ CallRuntime"); | 3237 Comment cmnt(masm_, "[ CallRuntime"); |
| 3094 Runtime::Function* function = node->function(); | 3238 Runtime::Function* function = node->function(); |
| 3095 | 3239 |
| 3096 if (function != NULL) { | 3240 if (function != NULL) { |
| 3097 // Push the arguments ("left-to-right"). | 3241 // Push the arguments ("left-to-right"). |
| 3098 int arg_count = args->length(); | 3242 int arg_count = args->length(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 3118 LoadAndSpill(args->at(i)); | 3262 LoadAndSpill(args->at(i)); |
| 3119 } | 3263 } |
| 3120 | 3264 |
| 3121 // Call the JS runtime function. | 3265 // Call the JS runtime function. |
| 3122 Handle<Code> stub = ComputeCallInitialize(args->length()); | 3266 Handle<Code> stub = ComputeCallInitialize(args->length()); |
| 3123 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 3267 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); |
| 3124 __ ldr(cp, frame_->Context()); | 3268 __ ldr(cp, frame_->Context()); |
| 3125 frame_->Drop(); | 3269 frame_->Drop(); |
| 3126 frame_->EmitPush(r0); | 3270 frame_->EmitPush(r0); |
| 3127 } | 3271 } |
| 3272 ASSERT(frame_->height() == original_height + 1); | |
| 3128 } | 3273 } |
| 3129 | 3274 |
| 3130 | 3275 |
| 3131 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 3276 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
| 3277 #ifdef DEBUG | |
| 3278 int original_height = frame_->height(); | |
| 3279 #endif | |
| 3132 VirtualFrame::SpilledScope spilled_scope(this); | 3280 VirtualFrame::SpilledScope spilled_scope(this); |
| 3133 Comment cmnt(masm_, "[ UnaryOperation"); | 3281 Comment cmnt(masm_, "[ UnaryOperation"); |
| 3134 | 3282 |
| 3135 Token::Value op = node->op(); | 3283 Token::Value op = node->op(); |
| 3136 | 3284 |
| 3137 if (op == Token::NOT) { | 3285 if (op == Token::NOT) { |
| 3138 LoadConditionAndSpill(node->expression(), | 3286 LoadConditionAndSpill(node->expression(), |
| 3139 NOT_INSIDE_TYPEOF, | 3287 NOT_INSIDE_TYPEOF, |
| 3140 false_target(), | 3288 false_target(), |
| 3141 true_target(), | 3289 true_target(), |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3254 __ mov(arg_count.reg(), Operand(0)); // not counting receiver | 3402 __ mov(arg_count.reg(), Operand(0)); // not counting receiver |
| 3255 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); | 3403 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); |
| 3256 continue_label.Bind(); | 3404 continue_label.Bind(); |
| 3257 break; | 3405 break; |
| 3258 } | 3406 } |
| 3259 default: | 3407 default: |
| 3260 UNREACHABLE(); | 3408 UNREACHABLE(); |
| 3261 } | 3409 } |
| 3262 frame_->EmitPush(r0); // r0 has result | 3410 frame_->EmitPush(r0); // r0 has result |
| 3263 } | 3411 } |
| 3412 ASSERT((has_cc() && frame_->height() == original_height) || | |
| 3413 (!has_cc() && frame_->height() == original_height + 1)); | |
| 3264 } | 3414 } |
| 3265 | 3415 |
| 3266 | 3416 |
| 3267 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 3417 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
| 3418 #ifdef DEBUG | |
| 3419 int original_height = frame_->height(); | |
| 3420 #endif | |
| 3268 VirtualFrame::SpilledScope spilled_scope(this); | 3421 VirtualFrame::SpilledScope spilled_scope(this); |
| 3269 Comment cmnt(masm_, "[ CountOperation"); | 3422 Comment cmnt(masm_, "[ CountOperation"); |
| 3270 | 3423 |
| 3271 bool is_postfix = node->is_postfix(); | 3424 bool is_postfix = node->is_postfix(); |
| 3272 bool is_increment = node->op() == Token::INC; | 3425 bool is_increment = node->op() == Token::INC; |
| 3273 | 3426 |
| 3274 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 3427 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); |
| 3275 bool is_const = (var != NULL && var->mode() == Variable::CONST); | 3428 bool is_const = (var != NULL && var->mode() == Variable::CONST); |
| 3276 | 3429 |
| 3277 // Postfix: Make room for the result. | 3430 // Postfix: Make room for the result. |
| 3278 if (is_postfix) { | 3431 if (is_postfix) { |
| 3279 __ mov(r0, Operand(0)); | 3432 __ mov(r0, Operand(0)); |
| 3280 frame_->EmitPush(r0); | 3433 frame_->EmitPush(r0); |
| 3281 } | 3434 } |
| 3282 | 3435 |
| 3283 { Reference target(this, node->expression()); | 3436 { Reference target(this, node->expression()); |
| 3284 if (target.is_illegal()) { | 3437 if (target.is_illegal()) { |
| 3285 // Spoof the virtual frame to have the expected height (one higher | 3438 // Spoof the virtual frame to have the expected height (one higher |
| 3286 // than on entry). | 3439 // than on entry). |
| 3287 if (!is_postfix) { | 3440 if (!is_postfix) { |
| 3288 __ mov(r0, Operand(Smi::FromInt(0))); | 3441 __ mov(r0, Operand(Smi::FromInt(0))); |
| 3289 frame_->EmitPush(r0); | 3442 frame_->EmitPush(r0); |
| 3290 } | 3443 } |
| 3444 ASSERT(frame_->height() == original_height + 1); | |
| 3291 return; | 3445 return; |
| 3292 } | 3446 } |
| 3293 target.GetValueAndSpill(NOT_INSIDE_TYPEOF); | 3447 target.GetValueAndSpill(NOT_INSIDE_TYPEOF); |
| 3294 frame_->EmitPop(r0); | 3448 frame_->EmitPop(r0); |
| 3295 | 3449 |
| 3296 JumpTarget slow(this); | 3450 JumpTarget slow(this); |
| 3297 JumpTarget exit(this); | 3451 JumpTarget exit(this); |
| 3298 | 3452 |
| 3299 // Load the value (1) into register r1. | 3453 // Load the value (1) into register r1. |
| 3300 __ mov(r1, Operand(Smi::FromInt(1))); | 3454 __ mov(r1, Operand(Smi::FromInt(1))); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3346 } | 3500 } |
| 3347 | 3501 |
| 3348 // Store the new value in the target if not const. | 3502 // Store the new value in the target if not const. |
| 3349 exit.Bind(); | 3503 exit.Bind(); |
| 3350 frame_->EmitPush(r0); | 3504 frame_->EmitPush(r0); |
| 3351 if (!is_const) target.SetValue(NOT_CONST_INIT); | 3505 if (!is_const) target.SetValue(NOT_CONST_INIT); |
| 3352 } | 3506 } |
| 3353 | 3507 |
| 3354 // Postfix: Discard the new value and use the old. | 3508 // Postfix: Discard the new value and use the old. |
| 3355 if (is_postfix) frame_->EmitPop(r0); | 3509 if (is_postfix) frame_->EmitPop(r0); |
| 3510 ASSERT(frame_->height() == original_height + 1); | |
| 3356 } | 3511 } |
| 3357 | 3512 |
| 3358 | 3513 |
| 3359 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 3514 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
| 3515 #ifdef DEBUG | |
| 3516 int original_height = frame_->height(); | |
| 3517 #endif | |
| 3360 VirtualFrame::SpilledScope spilled_scope(this); | 3518 VirtualFrame::SpilledScope spilled_scope(this); |
| 3361 Comment cmnt(masm_, "[ BinaryOperation"); | 3519 Comment cmnt(masm_, "[ BinaryOperation"); |
| 3362 Token::Value op = node->op(); | 3520 Token::Value op = node->op(); |
| 3363 | 3521 |
| 3364 // According to ECMA-262 section 11.11, page 58, the binary logical | 3522 // According to ECMA-262 section 11.11, page 58, the binary logical |
| 3365 // operators must yield the result of one of the two expressions | 3523 // operators must yield the result of one of the two expressions |
| 3366 // before any ToBoolean() conversions. This means that the value | 3524 // before any ToBoolean() conversions. This means that the value |
| 3367 // produced by a && or || operator is not necessarily a boolean. | 3525 // produced by a && or || operator is not necessarily a boolean. |
| 3368 | 3526 |
| 3369 // NOTE: If the left hand side produces a materialized value (not in | 3527 // NOTE: If the left hand side produces a materialized value (not in |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3471 LoadAndSpill(node->right()); | 3629 LoadAndSpill(node->right()); |
| 3472 SmiOperation(node->op(), lliteral->handle(), true); | 3630 SmiOperation(node->op(), lliteral->handle(), true); |
| 3473 | 3631 |
| 3474 } else { | 3632 } else { |
| 3475 LoadAndSpill(node->left()); | 3633 LoadAndSpill(node->left()); |
| 3476 LoadAndSpill(node->right()); | 3634 LoadAndSpill(node->right()); |
| 3477 GenericBinaryOperation(node->op()); | 3635 GenericBinaryOperation(node->op()); |
| 3478 } | 3636 } |
| 3479 frame_->EmitPush(r0); | 3637 frame_->EmitPush(r0); |
| 3480 } | 3638 } |
| 3639 ASSERT((has_cc() && frame_->height() == original_height) || | |
| 3640 (!has_cc() && frame_->height() == original_height + 1)); | |
| 3481 } | 3641 } |
| 3482 | 3642 |
| 3483 | 3643 |
| 3484 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 3644 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
| 3645 #ifdef DEBUG | |
| 3646 int original_height = frame_->height(); | |
| 3647 #endif | |
| 3485 VirtualFrame::SpilledScope spilled_scope(this); | 3648 VirtualFrame::SpilledScope spilled_scope(this); |
| 3486 __ ldr(r0, frame_->Function()); | 3649 __ ldr(r0, frame_->Function()); |
| 3487 frame_->EmitPush(r0); | 3650 frame_->EmitPush(r0); |
| 3651 ASSERT(frame_->height() == original_height + 1); | |
| 3488 } | 3652 } |
| 3489 | 3653 |
| 3490 | 3654 |
| 3491 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 3655 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
| 3656 #ifdef DEBUG | |
| 3657 int original_height = frame_->height(); | |
| 3658 #endif | |
| 3492 VirtualFrame::SpilledScope spilled_scope(this); | 3659 VirtualFrame::SpilledScope spilled_scope(this); |
| 3493 Comment cmnt(masm_, "[ CompareOperation"); | 3660 Comment cmnt(masm_, "[ CompareOperation"); |
| 3494 | 3661 |
| 3495 // Get the expressions from the node. | 3662 // Get the expressions from the node. |
| 3496 Expression* left = node->left(); | 3663 Expression* left = node->left(); |
| 3497 Expression* right = node->right(); | 3664 Expression* right = node->right(); |
| 3498 Token::Value op = node->op(); | 3665 Token::Value op = node->op(); |
| 3499 | 3666 |
| 3500 // To make null checks efficient, we check if either left or right is the | 3667 // To make null checks efficient, we check if either left or right is the |
| 3501 // literal 'null'. If so, we optimize the code by inlining a null check | 3668 // literal 'null'. If so, we optimize the code by inlining a null check |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 3524 false_target()->Branch(eq); | 3691 false_target()->Branch(eq); |
| 3525 | 3692 |
| 3526 // It can be an undetectable object. | 3693 // It can be an undetectable object. |
| 3527 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3694 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 3528 __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset)); | 3695 __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 3529 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); | 3696 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); |
| 3530 __ cmp(r0, Operand(1 << Map::kIsUndetectable)); | 3697 __ cmp(r0, Operand(1 << Map::kIsUndetectable)); |
| 3531 } | 3698 } |
| 3532 | 3699 |
| 3533 cc_reg_ = eq; | 3700 cc_reg_ = eq; |
| 3701 ASSERT(has_cc() && frame_->height() == original_height); | |
| 3534 return; | 3702 return; |
| 3535 } | 3703 } |
| 3536 } | 3704 } |
| 3537 | 3705 |
| 3538 // To make typeof testing for natives implemented in JavaScript really | 3706 // To make typeof testing for natives implemented in JavaScript really |
| 3539 // efficient, we generate special code for expressions of the form: | 3707 // efficient, we generate special code for expressions of the form: |
| 3540 // 'typeof <expression> == <string>'. | 3708 // 'typeof <expression> == <string>'. |
| 3541 UnaryOperation* operation = left->AsUnaryOperation(); | 3709 UnaryOperation* operation = left->AsUnaryOperation(); |
| 3542 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 3710 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
| 3543 (operation != NULL && operation->op() == Token::TYPEOF) && | 3711 (operation != NULL && operation->op() == Token::TYPEOF) && |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3619 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); | 3787 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); |
| 3620 false_target()->Branch(lt); | 3788 false_target()->Branch(lt); |
| 3621 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); | 3789 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); |
| 3622 cc_reg_ = le; | 3790 cc_reg_ = le; |
| 3623 | 3791 |
| 3624 } else { | 3792 } else { |
| 3625 // Uncommon case: typeof testing against a string literal that is | 3793 // Uncommon case: typeof testing against a string literal that is |
| 3626 // never returned from the typeof operator. | 3794 // never returned from the typeof operator. |
| 3627 false_target()->Jump(); | 3795 false_target()->Jump(); |
| 3628 } | 3796 } |
| 3797 ASSERT(!has_valid_frame() || | |
| 3798 (has_cc() && frame_->height() == original_height)); | |
| 3629 return; | 3799 return; |
| 3630 } | 3800 } |
| 3631 | 3801 |
| 3632 LoadAndSpill(left); | 3802 LoadAndSpill(left); |
| 3633 LoadAndSpill(right); | 3803 LoadAndSpill(right); |
| 3634 switch (op) { | 3804 switch (op) { |
| 3635 case Token::EQ: | 3805 case Token::EQ: |
| 3636 Comparison(eq, false); | 3806 Comparison(eq, false); |
| 3637 break; | 3807 break; |
| 3638 | 3808 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3677 &arg_count, | 3847 &arg_count, |
| 3678 2); | 3848 2); |
| 3679 __ tst(result.reg(), Operand(result.reg())); | 3849 __ tst(result.reg(), Operand(result.reg())); |
| 3680 cc_reg_ = eq; | 3850 cc_reg_ = eq; |
| 3681 break; | 3851 break; |
| 3682 } | 3852 } |
| 3683 | 3853 |
| 3684 default: | 3854 default: |
| 3685 UNREACHABLE(); | 3855 UNREACHABLE(); |
| 3686 } | 3856 } |
| 3857 ASSERT((has_cc() && frame_->height() == original_height) || | |
| 3858 (!has_cc() && frame_->height() == original_height + 1)); | |
| 3687 } | 3859 } |
| 3688 | 3860 |
| 3689 | 3861 |
| 3690 #ifdef DEBUG | 3862 #ifdef DEBUG |
| 3691 bool CodeGenerator::HasValidEntryRegisters() { return true; } | 3863 bool CodeGenerator::HasValidEntryRegisters() { return true; } |
| 3692 #endif | 3864 #endif |
| 3693 | 3865 |
| 3694 | 3866 |
| 3695 bool CodeGenerator::IsActualFunctionReturn(JumpTarget* target) { | 3867 bool CodeGenerator::IsActualFunctionReturn(JumpTarget* target) { |
| 3696 return (target == &function_return_ && !function_return_is_shadowed_); | 3868 return (target == &function_return_ && !function_return_is_shadowed_); |
| (...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4829 __ mov(r2, Operand(0)); | 5001 __ mov(r2, Operand(0)); |
| 4830 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5002 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
| 4831 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 5003 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
| 4832 RelocInfo::CODE_TARGET); | 5004 RelocInfo::CODE_TARGET); |
| 4833 } | 5005 } |
| 4834 | 5006 |
| 4835 | 5007 |
| 4836 #undef __ | 5008 #undef __ |
| 4837 | 5009 |
| 4838 } } // namespace v8::internal | 5010 } } // namespace v8::internal |
| OLD | NEW |