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

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

Issue 9328: Initial (stub) port of jump targets to the ARM platform.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years, 1 month 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 typeof_state_(NOT_INSIDE_TYPEOF), 57 typeof_state_(NOT_INSIDE_TYPEOF),
58 true_target_(NULL), 58 true_target_(NULL),
59 false_target_(NULL), 59 false_target_(NULL),
60 previous_(NULL) { 60 previous_(NULL) {
61 owner_->set_state(this); 61 owner_->set_state(this);
62 } 62 }
63 63
64 64
65 CodeGenState::CodeGenState(CodeGenerator* owner, 65 CodeGenState::CodeGenState(CodeGenerator* owner,
66 TypeofState typeof_state, 66 TypeofState typeof_state,
67 Label* true_target, 67 JumpTarget* true_target,
68 Label* false_target) 68 JumpTarget* false_target)
69 : owner_(owner), 69 : owner_(owner),
70 typeof_state_(typeof_state), 70 typeof_state_(typeof_state),
71 true_target_(true_target), 71 true_target_(true_target),
72 false_target_(false_target), 72 false_target_(false_target),
73 previous_(owner->state()) { 73 previous_(owner->state()) {
74 owner_->set_state(this); 74 owner_->set_state(this);
75 } 75 }
76 76
77 77
78 CodeGenState::~CodeGenState() { 78 CodeGenState::~CodeGenState() {
(...skipping 30 matching lines...) Expand all
109 void CodeGenerator::GenCode(FunctionLiteral* fun) { 109 void CodeGenerator::GenCode(FunctionLiteral* fun) {
110 ZoneList<Statement*>* body = fun->body(); 110 ZoneList<Statement*>* body = fun->body();
111 111
112 // Initialize state. 112 // Initialize state.
113 ASSERT(scope_ == NULL); 113 ASSERT(scope_ == NULL);
114 scope_ = fun->scope(); 114 scope_ = fun->scope();
115 ASSERT(frame_ == NULL); 115 ASSERT(frame_ == NULL);
116 VirtualFrame virtual_frame(this); 116 VirtualFrame virtual_frame(this);
117 frame_ = &virtual_frame; 117 frame_ = &virtual_frame;
118 cc_reg_ = al; 118 cc_reg_ = al;
119 function_return_.set_code_generator(this);
119 { 120 {
120 CodeGenState state(this); 121 CodeGenState state(this);
121 122
122 // Entry 123 // Entry
123 // stack: function, receiver, arguments, return address 124 // stack: function, receiver, arguments, return address
124 // r0: number of arguments 125 // r0: number of arguments
125 // sp: stack pointer 126 // sp: stack pointer
126 // fp: frame pointer 127 // fp: frame pointer
127 // pp: caller's parameter pointer 128 // pp: caller's parameter pointer
128 // cp: callee's context 129 // cp: callee's context
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 } 266 }
266 267
267 // exit 268 // exit
268 // r0: result 269 // r0: result
269 // sp: stack pointer 270 // sp: stack pointer
270 // fp: frame pointer 271 // fp: frame pointer
271 // pp: parameter pointer 272 // pp: parameter pointer
272 // cp: callee's context 273 // cp: callee's context
273 __ mov(r0, Operand(Factory::undefined_value())); 274 __ mov(r0, Operand(Factory::undefined_value()));
274 275
275 __ bind(&function_return_); 276 function_return_.Bind();
276 if (FLAG_trace) { 277 if (FLAG_trace) {
277 // Push the return value on the stack as the parameter. 278 // Push the return value on the stack as the parameter.
278 // Runtime::TraceExit returns the parameter as it is. 279 // Runtime::TraceExit returns the parameter as it is.
279 __ push(r0); 280 __ push(r0);
280 __ CallRuntime(Runtime::kTraceExit, 1); 281 __ CallRuntime(Runtime::kTraceExit, 1);
281 } 282 }
282 283
283 // Tear down the frame which will restore the caller's frame pointer and the 284 // Tear down the frame which will restore the caller's frame pointer and the
284 // link register. 285 // link register.
285 ExitJSFrame(); 286 ExitJSFrame();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 } 346 }
346 } 347 }
347 348
348 349
349 // Loads a value on the stack. If it is a boolean value, the result may have 350 // Loads a value on the stack. If it is a boolean value, the result may have
350 // been (partially) translated into branches, or it may have set the condition 351 // been (partially) translated into branches, or it may have set the condition
351 // code register. If force_cc is set, the value is forced to set the condition 352 // code register. If force_cc is set, the value is forced to set the condition
352 // code register and no value is pushed. If the condition code register was set, 353 // code register and no value is pushed. If the condition code register was set,
353 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. 354 // has_cc() is true and cc_reg_ contains the condition to test for 'true'.
354 void CodeGenerator::LoadCondition(Expression* x, 355 void CodeGenerator::LoadCondition(Expression* x,
355 TypeofState typeof_state, 356 TypeofState typeof_state,
356 Label* true_target, 357 JumpTarget* true_target,
357 Label* false_target, 358 JumpTarget* false_target,
358 bool force_cc) { 359 bool force_cc) {
359 ASSERT(!has_cc()); 360 ASSERT(!has_cc());
360 361
361 { CodeGenState new_state(this, typeof_state, true_target, false_target); 362 { CodeGenState new_state(this, typeof_state, true_target, false_target);
362 Visit(x); 363 Visit(x);
363 } 364 }
364 if (force_cc && !has_cc()) { 365 if (force_cc && !has_cc()) {
365 // Convert the TOS value to a boolean in the condition code register. 366 // Convert the TOS value to a boolean in the condition code register.
366 ToBoolean(true_target, false_target); 367 ToBoolean(true_target, false_target);
367 } 368 }
368 ASSERT(has_cc() || !force_cc); 369 ASSERT(has_cc() || !force_cc);
369 } 370 }
370 371
371 372
372 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 373 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
373 Label true_target; 374 JumpTarget true_target(this);
374 Label false_target; 375 JumpTarget false_target(this);
375 LoadCondition(x, typeof_state, &true_target, &false_target, false); 376 LoadCondition(x, typeof_state, &true_target, &false_target, false);
376 377
377 if (has_cc()) { 378 if (has_cc()) {
378 // convert cc_reg_ into a bool 379 // convert cc_reg_ into a bool
379 Label loaded, materialize_true; 380 Label loaded, materialize_true;
380 __ b(cc_reg_, &materialize_true); 381 __ b(cc_reg_, &materialize_true);
381 __ mov(r0, Operand(Factory::false_value())); 382 __ mov(r0, Operand(Factory::false_value()));
382 __ push(r0); 383 __ push(r0);
383 __ b(&loaded); 384 __ b(&loaded);
384 __ bind(&materialize_true); 385 __ bind(&materialize_true);
385 __ mov(r0, Operand(Factory::true_value())); 386 __ mov(r0, Operand(Factory::true_value()));
386 __ push(r0); 387 __ push(r0);
387 __ bind(&loaded); 388 __ bind(&loaded);
388 cc_reg_ = al; 389 cc_reg_ = al;
389 } 390 }
390 391
391 if (true_target.is_linked() || false_target.is_linked()) { 392 if (true_target.is_linked() || false_target.is_linked()) {
392 // we have at least one condition value 393 // we have at least one condition value
393 // that has been "translated" into a branch, 394 // that has been "translated" into a branch,
394 // thus it needs to be loaded explicitly again 395 // thus it needs to be loaded explicitly again
395 Label loaded; 396 Label loaded;
396 __ b(&loaded); // don't lose current TOS 397 __ b(&loaded); // don't lose current TOS
397 bool both = true_target.is_linked() && false_target.is_linked(); 398 bool both = true_target.is_linked() && false_target.is_linked();
398 // reincarnate "true", if necessary 399 // reincarnate "true", if necessary
399 if (true_target.is_linked()) { 400 if (true_target.is_linked()) {
400 __ bind(&true_target); 401 true_target.Bind();
401 __ mov(r0, Operand(Factory::true_value())); 402 __ mov(r0, Operand(Factory::true_value()));
402 __ push(r0); 403 __ push(r0);
403 } 404 }
404 // if both "true" and "false" need to be reincarnated, 405 // if both "true" and "false" need to be reincarnated,
405 // jump across code for "false" 406 // jump across code for "false"
406 if (both) 407 if (both)
407 __ b(&loaded); 408 __ b(&loaded);
408 // reincarnate "false", if necessary 409 // reincarnate "false", if necessary
409 if (false_target.is_linked()) { 410 if (false_target.is_linked()) {
410 __ bind(&false_target); 411 false_target.Bind();
411 __ mov(r0, Operand(Factory::false_value())); 412 __ mov(r0, Operand(Factory::false_value()));
412 __ push(r0); 413 __ push(r0);
413 } 414 }
414 // everything is loaded at this point 415 // everything is loaded at this point
415 __ bind(&loaded); 416 __ bind(&loaded);
416 } 417 }
417 ASSERT(!has_cc()); 418 ASSERT(!has_cc());
418 } 419 }
419 420
420 421
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 __ pop(r0); 517 __ pop(r0);
517 __ add(sp, sp, Operand(size * kPointerSize)); 518 __ add(sp, sp, Operand(size * kPointerSize));
518 __ push(r0); 519 __ push(r0);
519 } 520 }
520 } 521 }
521 522
522 523
523 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given 524 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
524 // register to a boolean in the condition code register. The code 525 // register to a boolean in the condition code register. The code
525 // may jump to 'false_target' in case the register converts to 'false'. 526 // may jump to 'false_target' in case the register converts to 'false'.
526 void CodeGenerator::ToBoolean(Label* true_target, 527 void CodeGenerator::ToBoolean(JumpTarget* true_target,
527 Label* false_target) { 528 JumpTarget* false_target) {
528 // Note: The generated code snippet does not change stack variables. 529 // Note: The generated code snippet does not change stack variables.
529 // Only the condition code should be set. 530 // Only the condition code should be set.
530 __ pop(r0); 531 __ pop(r0);
531 532
532 // Fast case checks 533 // Fast case checks
533 534
534 // Check if the value is 'false'. 535 // Check if the value is 'false'.
535 __ cmp(r0, Operand(Factory::false_value())); 536 __ cmp(r0, Operand(Factory::false_value()));
536 __ b(eq, false_target); 537 false_target->Branch(eq);
537 538
538 // Check if the value is 'true'. 539 // Check if the value is 'true'.
539 __ cmp(r0, Operand(Factory::true_value())); 540 __ cmp(r0, Operand(Factory::true_value()));
540 __ b(eq, true_target); 541 true_target->Branch(eq);
541 542
542 // Check if the value is 'undefined'. 543 // Check if the value is 'undefined'.
543 __ cmp(r0, Operand(Factory::undefined_value())); 544 __ cmp(r0, Operand(Factory::undefined_value()));
544 __ b(eq, false_target); 545 false_target->Branch(eq);
545 546
546 // Check if the value is a smi. 547 // Check if the value is a smi.
547 __ cmp(r0, Operand(Smi::FromInt(0))); 548 __ cmp(r0, Operand(Smi::FromInt(0)));
548 __ b(eq, false_target); 549 false_target->Branch(eq);
549 __ tst(r0, Operand(kSmiTagMask)); 550 __ tst(r0, Operand(kSmiTagMask));
550 __ b(eq, true_target); 551 true_target->Branch(eq);
551 552
552 // Slow case: call the runtime. 553 // Slow case: call the runtime.
553 __ push(r0); 554 __ push(r0);
554 __ CallRuntime(Runtime::kToBool, 1); 555 __ CallRuntime(Runtime::kToBool, 1);
555 556
556 // Convert result (r0) to condition code 557 // Convert result (r0) to condition code
557 __ cmp(r0, Operand(Factory::false_value())); 558 __ cmp(r0, Operand(Factory::false_value()));
558 559
559 cc_reg_ = ne; 560 cc_reg_ = ne;
560 } 561 }
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 // Use the shared code stub to call the function. 993 // Use the shared code stub to call the function.
993 CallFunctionStub call_function(args->length()); 994 CallFunctionStub call_function(args->length());
994 __ CallStub(&call_function); 995 __ CallStub(&call_function);
995 996
996 // Restore context and pop function from the stack. 997 // Restore context and pop function from the stack.
997 __ ldr(cp, frame_->Context()); 998 __ ldr(cp, frame_->Context());
998 __ pop(); // discard the TOS 999 __ pop(); // discard the TOS
999 } 1000 }
1000 1001
1001 1002
1002 void CodeGenerator::Branch(bool if_true, Label* L) { 1003 void CodeGenerator::Branch(bool if_true, JumpTarget* target) {
1003 ASSERT(has_cc()); 1004 ASSERT(has_cc());
1004 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1005 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
1005 __ b(cc, L); 1006 target->Branch(cc);
1006 cc_reg_ = al; 1007 cc_reg_ = al;
1007 } 1008 }
1008 1009
1009 1010
1010 void CodeGenerator::CheckStack() { 1011 void CodeGenerator::CheckStack() {
1011 if (FLAG_check_stack) { 1012 if (FLAG_check_stack) {
1012 Comment cmnt(masm_, "[ check stack"); 1013 Comment cmnt(masm_, "[ check stack");
1013 StackCheckStub stub; 1014 StackCheckStub stub;
1014 __ CallStub(&stub); 1015 __ CallStub(&stub);
1015 } 1016 }
1016 } 1017 }
1017 1018
1018 1019
1019 void CodeGenerator::VisitBlock(Block* node) { 1020 void CodeGenerator::VisitBlock(Block* node) {
1020 Comment cmnt(masm_, "[ Block"); 1021 Comment cmnt(masm_, "[ Block");
1021 if (FLAG_debug_info) RecordStatementPosition(node); 1022 if (FLAG_debug_info) RecordStatementPosition(node);
1022 node->set_break_stack_height(break_stack_height_); 1023 node->set_break_stack_height(break_stack_height_);
1024 node->break_target()->set_code_generator(this);
1023 VisitStatements(node->statements()); 1025 VisitStatements(node->statements());
1024 __ bind(node->break_target()); 1026 node->break_target()->Bind();
1025 } 1027 }
1026 1028
1027 1029
1028 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1030 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1029 __ mov(r0, Operand(pairs)); 1031 __ mov(r0, Operand(pairs));
1030 __ push(r0); 1032 __ push(r0);
1031 __ push(cp); 1033 __ push(cp);
1032 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 1034 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
1033 __ push(r0); 1035 __ push(r0);
1034 __ CallRuntime(Runtime::kDeclareGlobals, 3); 1036 __ CallRuntime(Runtime::kDeclareGlobals, 3);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 1121
1120 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1122 void CodeGenerator::VisitIfStatement(IfStatement* node) {
1121 Comment cmnt(masm_, "[ IfStatement"); 1123 Comment cmnt(masm_, "[ IfStatement");
1122 // Generate different code depending on which 1124 // Generate different code depending on which
1123 // parts of the if statement are present or not. 1125 // parts of the if statement are present or not.
1124 bool has_then_stm = node->HasThenStatement(); 1126 bool has_then_stm = node->HasThenStatement();
1125 bool has_else_stm = node->HasElseStatement(); 1127 bool has_else_stm = node->HasElseStatement();
1126 1128
1127 if (FLAG_debug_info) RecordStatementPosition(node); 1129 if (FLAG_debug_info) RecordStatementPosition(node);
1128 1130
1129 Label exit; 1131 JumpTarget exit(this);
1130 if (has_then_stm && has_else_stm) { 1132 if (has_then_stm && has_else_stm) {
1131 Comment cmnt(masm_, "[ IfThenElse"); 1133 Comment cmnt(masm_, "[ IfThenElse");
1132 Label then; 1134 JumpTarget then(this);
1133 Label else_; 1135 JumpTarget else_(this);
1134 // if (cond) 1136 // if (cond)
1135 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 1137 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
1136 Branch(false, &else_); 1138 Branch(false, &else_);
1137 // then 1139 // then
1138 __ bind(&then); 1140 then.Bind();
1139 Visit(node->then_statement()); 1141 Visit(node->then_statement());
1140 __ b(&exit); 1142 exit.Jump();
1141 // else 1143 // else
1142 __ bind(&else_); 1144 else_.Bind();
1143 Visit(node->else_statement()); 1145 Visit(node->else_statement());
1144 1146
1145 } else if (has_then_stm) { 1147 } else if (has_then_stm) {
1146 Comment cmnt(masm_, "[ IfThen"); 1148 Comment cmnt(masm_, "[ IfThen");
1147 ASSERT(!has_else_stm); 1149 ASSERT(!has_else_stm);
1148 Label then; 1150 JumpTarget then(this);
1149 // if (cond) 1151 // if (cond)
1150 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true); 1152 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true);
1151 Branch(false, &exit); 1153 Branch(false, &exit);
1152 // then 1154 // then
1153 __ bind(&then); 1155 then.Bind();
1154 Visit(node->then_statement()); 1156 Visit(node->then_statement());
1155 1157
1156 } else if (has_else_stm) { 1158 } else if (has_else_stm) {
1157 Comment cmnt(masm_, "[ IfElse"); 1159 Comment cmnt(masm_, "[ IfElse");
1158 ASSERT(!has_then_stm); 1160 ASSERT(!has_then_stm);
1159 Label else_; 1161 JumpTarget else_(this);
1160 // if (!cond) 1162 // if (!cond)
1161 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true); 1163 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true);
1162 Branch(true, &exit); 1164 Branch(true, &exit);
1163 // else 1165 // else
1164 __ bind(&else_); 1166 else_.Bind();
1165 Visit(node->else_statement()); 1167 Visit(node->else_statement());
1166 1168
1167 } else { 1169 } else {
1168 Comment cmnt(masm_, "[ If"); 1170 Comment cmnt(masm_, "[ If");
1169 ASSERT(!has_then_stm && !has_else_stm); 1171 ASSERT(!has_then_stm && !has_else_stm);
1170 // if (cond) 1172 // if (cond)
1171 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1173 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1172 if (has_cc()) { 1174 if (has_cc()) {
1173 cc_reg_ = al; 1175 cc_reg_ = al;
1174 } else { 1176 } else {
1175 __ pop(r0); // __ Pop(no_reg) 1177 __ pop(r0); // __ Pop(no_reg)
1176 } 1178 }
1177 } 1179 }
1178 1180
1179 // end 1181 // end
1180 __ bind(&exit); 1182 exit.Bind();
1181 } 1183 }
1182 1184
1183 1185
1184 void CodeGenerator::CleanStack(int num_bytes) { 1186 void CodeGenerator::CleanStack(int num_bytes) {
1185 ASSERT(num_bytes >= 0); 1187 ASSERT(num_bytes >= 0);
1186 if (num_bytes > 0) { 1188 if (num_bytes > 0) {
1187 __ add(sp, sp, Operand(num_bytes)); 1189 __ add(sp, sp, Operand(num_bytes));
1188 } 1190 }
1189 } 1191 }
1190 1192
1191 1193
1192 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1194 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1193 Comment cmnt(masm_, "[ ContinueStatement"); 1195 Comment cmnt(masm_, "[ ContinueStatement");
1194 if (FLAG_debug_info) RecordStatementPosition(node); 1196 if (FLAG_debug_info) RecordStatementPosition(node);
1195 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1197 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1196 __ b(node->target()->continue_target()); 1198 node->target()->continue_target()->Jump();
1197 } 1199 }
1198 1200
1199 1201
1200 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1202 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1201 Comment cmnt(masm_, "[ BreakStatement"); 1203 Comment cmnt(masm_, "[ BreakStatement");
1202 if (FLAG_debug_info) RecordStatementPosition(node); 1204 if (FLAG_debug_info) RecordStatementPosition(node);
1203 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1205 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1204 __ b(node->target()->break_target()); 1206 node->target()->break_target()->Jump();
1205 } 1207 }
1206 1208
1207 1209
1208 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1210 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1209 Comment cmnt(masm_, "[ ReturnStatement"); 1211 Comment cmnt(masm_, "[ ReturnStatement");
1210 if (FLAG_debug_info) RecordStatementPosition(node); 1212 if (FLAG_debug_info) RecordStatementPosition(node);
1211 Load(node->expression()); 1213 Load(node->expression());
1212 // Move the function result into r0. 1214 // Move the function result into r0.
1213 __ pop(r0); 1215 __ pop(r0);
1214 1216
1215 __ b(&function_return_); 1217 function_return_.Jump();
1216 } 1218 }
1217 1219
1218 1220
1219 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1221 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1220 Comment cmnt(masm_, "[ WithEnterStatement"); 1222 Comment cmnt(masm_, "[ WithEnterStatement");
1221 if (FLAG_debug_info) RecordStatementPosition(node); 1223 if (FLAG_debug_info) RecordStatementPosition(node);
1222 Load(node->expression()); 1224 Load(node->expression());
1223 __ CallRuntime(Runtime::kPushContext, 1); 1225 __ CallRuntime(Runtime::kPushContext, 1);
1224 if (kDebug) { 1226 if (kDebug) {
1225 Label verified_true; 1227 Label verified_true;
(...skipping 22 matching lines...) Expand all
1248 1250
1249 int CodeGenerator::FastCaseSwitchMinCaseCount() { 1251 int CodeGenerator::FastCaseSwitchMinCaseCount() {
1250 return kFastSwitchMinCaseCount; 1252 return kFastSwitchMinCaseCount;
1251 } 1253 }
1252 1254
1253 1255
1254 void CodeGenerator::GenerateFastCaseSwitchJumpTable( 1256 void CodeGenerator::GenerateFastCaseSwitchJumpTable(
1255 SwitchStatement* node, 1257 SwitchStatement* node,
1256 int min_index, 1258 int min_index,
1257 int range, 1259 int range,
1258 Label* fail_label, 1260 JumpTarget* fail_label,
1259 Vector<Label*> case_targets, 1261 Vector<JumpTarget*> case_targets,
1260 Vector<Label> case_labels) { 1262 Vector<JumpTarget> case_labels) {
1261 1263
1262 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); 1264 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
1263 1265
1264 __ pop(r0); 1266 __ pop(r0);
1265 1267
1266 // Test for a Smi value in a HeapNumber. 1268 // Test for a Smi value in a HeapNumber.
1267 Label is_smi; 1269 Label is_smi;
1268 __ tst(r0, Operand(kSmiTagMask)); 1270 __ tst(r0, Operand(kSmiTagMask));
1269 __ b(eq, &is_smi); 1271 __ b(eq, &is_smi);
1270 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag)); 1272 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
1271 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag)); 1273 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
1272 __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); 1274 __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
1273 __ b(ne, fail_label); 1275 fail_label->Branch(ne);
1274 __ push(r0); 1276 __ push(r0);
1275 __ CallRuntime(Runtime::kNumberToSmi, 1); 1277 __ CallRuntime(Runtime::kNumberToSmi, 1);
1276 __ bind(&is_smi); 1278 __ bind(&is_smi);
1277 1279
1278 if (min_index != 0) { 1280 if (min_index != 0) {
1279 // Small positive numbers can be immediate operands. 1281 // Small positive numbers can be immediate operands.
1280 if (min_index < 0) { 1282 if (min_index < 0) {
1281 // If min_index is Smi::kMinValue, -min_index is not a Smi. 1283 // If min_index is Smi::kMinValue, -min_index is not a Smi.
1282 if (Smi::IsValid(-min_index)) { 1284 if (Smi::IsValid(-min_index)) {
1283 __ add(r0, r0, Operand(Smi::FromInt(-min_index))); 1285 __ add(r0, r0, Operand(Smi::FromInt(-min_index)));
1284 } else { 1286 } else {
1285 __ add(r0, r0, Operand(Smi::FromInt(-min_index - 1))); 1287 __ add(r0, r0, Operand(Smi::FromInt(-min_index - 1)));
1286 __ add(r0, r0, Operand(Smi::FromInt(1))); 1288 __ add(r0, r0, Operand(Smi::FromInt(1)));
1287 } 1289 }
1288 } else { 1290 } else {
1289 __ sub(r0, r0, Operand(Smi::FromInt(min_index))); 1291 __ sub(r0, r0, Operand(Smi::FromInt(min_index)));
1290 } 1292 }
1291 } 1293 }
1292 __ tst(r0, Operand(0x80000000 | kSmiTagMask)); 1294 __ tst(r0, Operand(0x80000000 | kSmiTagMask));
1293 __ b(ne, fail_label); 1295 fail_label->Branch(ne);
1294 __ cmp(r0, Operand(Smi::FromInt(range))); 1296 __ cmp(r0, Operand(Smi::FromInt(range)));
1295 __ b(ge, fail_label); 1297 fail_label->Branch(ge);
1296 __ add(pc, pc, Operand(r0, LSL, 2 - kSmiTagSize)); 1298 __ add(pc, pc, Operand(r0, LSL, 2 - kSmiTagSize));
1297 // One extra instruction offsets the table, so the table's start address is 1299 // One extra instruction offsets the table, so the table's start address is
1298 // the pc-register at the above add. 1300 // the pc-register at the above add.
1299 __ stop("Unreachable: Switch table alignment"); 1301 __ stop("Unreachable: Switch table alignment");
1300 1302
1303 JumpTarget table_start(this);
1304 table_start.Bind();
1301 // Table containing branch operations. 1305 // Table containing branch operations.
1302 for (int i = 0; i < range; i++) { 1306 for (int i = 0; i < range; i++) {
1303 __ b(case_targets[i]); 1307 case_targets[i]->Jump();
1304 } 1308 }
1305 1309
1306 GenerateFastCaseSwitchCases(node, case_labels); 1310 GenerateFastCaseSwitchCases(node, case_labels, &table_start);
1307 } 1311 }
1308 1312
1309 1313
1310 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1314 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1311 Comment cmnt(masm_, "[ SwitchStatement"); 1315 Comment cmnt(masm_, "[ SwitchStatement");
1312 if (FLAG_debug_info) RecordStatementPosition(node); 1316 if (FLAG_debug_info) RecordStatementPosition(node);
1313 node->set_break_stack_height(break_stack_height_); 1317 node->set_break_stack_height(break_stack_height_);
1318 node->break_target()->set_code_generator(this);
1314 1319
1315 Load(node->tag()); 1320 Load(node->tag());
1316 1321
1317 if (TryGenerateFastCaseSwitchStatement(node)) { 1322 if (TryGenerateFastCaseSwitchStatement(node)) {
1318 return; 1323 return;
1319 } 1324 }
1320 1325
1321 Label next, fall_through, default_case; 1326 JumpTarget next(this);
1327 Label fall_through, default_case;
1322 ZoneList<CaseClause*>* cases = node->cases(); 1328 ZoneList<CaseClause*>* cases = node->cases();
1323 int length = cases->length(); 1329 int length = cases->length();
1324 1330
1325 for (int i = 0; i < length; i++) { 1331 for (int i = 0; i < length; i++) {
1326 CaseClause* clause = cases->at(i); 1332 CaseClause* clause = cases->at(i);
1327 1333
1328 Comment cmnt(masm_, "[ case clause"); 1334 Comment cmnt(masm_, "[ case clause");
1329 1335
1330 if (clause->is_default()) { 1336 if (clause->is_default()) {
1331 // Continue matching cases. The program will execute the default case's 1337 // Continue matching cases. The program will execute the default case's
1332 // statements if it does not match any of the cases. 1338 // statements if it does not match any of the cases.
1333 __ b(&next); 1339 next.Jump();
1334 1340
1335 // Bind the default case label, so we can branch to it when we 1341 // Bind the default case label, so we can branch to it when we
1336 // have compared against all other cases. 1342 // have compared against all other cases.
1337 ASSERT(default_case.is_unused()); // at most one default clause 1343 ASSERT(default_case.is_unused()); // at most one default clause
1338 __ bind(&default_case); 1344 __ bind(&default_case);
1339 } else { 1345 } else {
1340 __ bind(&next); 1346 next.Bind();
1341 next.Unuse(); 1347 next.Unuse();
1342 __ ldr(r0, frame_->Top()); 1348 __ ldr(r0, frame_->Top());
1343 __ push(r0); // duplicate TOS 1349 __ push(r0); // duplicate TOS
1344 Load(clause->label()); 1350 Load(clause->label());
1345 Comparison(eq, true); 1351 Comparison(eq, true);
1346 Branch(false, &next); 1352 Branch(false, &next);
1347 } 1353 }
1348 1354
1349 // Entering the case statement for the first time. Remove the switch value 1355 // Entering the case statement for the first time. Remove the switch value
1350 // from the stack. 1356 // from the stack.
1351 __ pop(r0); 1357 __ pop(r0);
1352 1358
1353 // Generate code for the body. 1359 // Generate code for the body.
1354 // This is also the target for the fall through from the previous case's 1360 // This is also the target for the fall through from the previous case's
1355 // statements which has to skip over the matching code and the popping of 1361 // statements which has to skip over the matching code and the popping of
1356 // the switch value. 1362 // the switch value.
1357 __ bind(&fall_through); 1363 __ bind(&fall_through);
1358 fall_through.Unuse(); 1364 fall_through.Unuse();
1359 VisitStatements(clause->statements()); 1365 VisitStatements(clause->statements());
1360 __ b(&fall_through); 1366 __ b(&fall_through);
1361 } 1367 }
1362 1368
1363 __ bind(&next); 1369 next.Bind();
1364 // Reached the end of the case statements without matching any of the cases. 1370 // Reached the end of the case statements without matching any of the cases.
1365 if (default_case.is_bound()) { 1371 if (default_case.is_bound()) {
1366 // A default case exists -> execute its statements. 1372 // A default case exists -> execute its statements.
1367 __ b(&default_case); 1373 __ b(&default_case);
1368 } else { 1374 } else {
1369 // Remove the switch value from the stack. 1375 // Remove the switch value from the stack.
1370 __ pop(r0); 1376 __ pop(r0);
1371 } 1377 }
1372 1378
1373 __ bind(&fall_through); 1379 __ bind(&fall_through);
1374 __ bind(node->break_target()); 1380 node->break_target()->Bind();
1375 } 1381 }
1376 1382
1377 1383
1378 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1384 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1379 Comment cmnt(masm_, "[ LoopStatement"); 1385 Comment cmnt(masm_, "[ LoopStatement");
1380 if (FLAG_debug_info) RecordStatementPosition(node); 1386 if (FLAG_debug_info) RecordStatementPosition(node);
1381 node->set_break_stack_height(break_stack_height_); 1387 node->set_break_stack_height(break_stack_height_);
1388 node->break_target()->set_code_generator(this);
1389 node->continue_target()->set_code_generator(this);
1382 1390
1383 // simple condition analysis 1391 // simple condition analysis
1384 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 1392 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
1385 if (node->cond() == NULL) { 1393 if (node->cond() == NULL) {
1386 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1394 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1387 info = ALWAYS_TRUE; 1395 info = ALWAYS_TRUE;
1388 } else { 1396 } else {
1389 Literal* lit = node->cond()->AsLiteral(); 1397 Literal* lit = node->cond()->AsLiteral();
1390 if (lit != NULL) { 1398 if (lit != NULL) {
1391 if (lit->IsTrue()) { 1399 if (lit->IsTrue()) {
1392 info = ALWAYS_TRUE; 1400 info = ALWAYS_TRUE;
1393 } else if (lit->IsFalse()) { 1401 } else if (lit->IsFalse()) {
1394 info = ALWAYS_FALSE; 1402 info = ALWAYS_FALSE;
1395 } 1403 }
1396 } 1404 }
1397 } 1405 }
1398 1406
1399 Label loop, entry; 1407 JumpTarget loop(this);
1408 Label entry;
1400 1409
1401 // init 1410 // init
1402 if (node->init() != NULL) { 1411 if (node->init() != NULL) {
1403 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1412 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1404 Visit(node->init()); 1413 Visit(node->init());
1405 } 1414 }
1406 if (node->type() != LoopStatement::DO_LOOP && info != ALWAYS_TRUE) { 1415 if (node->type() != LoopStatement::DO_LOOP && info != ALWAYS_TRUE) {
1407 __ b(&entry); 1416 __ b(&entry);
1408 } 1417 }
1409 1418
1410 // body 1419 // body
1411 __ bind(&loop); 1420 loop.Bind();
1412 Visit(node->body()); 1421 Visit(node->body());
1413 1422
1414 // next 1423 // next
1415 __ bind(node->continue_target()); 1424 node->continue_target()->Bind();
1416 if (node->next() != NULL) { 1425 if (node->next() != NULL) {
1417 // Record source position of the statement as this code which is after the 1426 // Record source position of the statement as this code which is after the
1418 // code for the body actually belongs to the loop statement and not the 1427 // code for the body actually belongs to the loop statement and not the
1419 // body. 1428 // body.
1420 if (FLAG_debug_info) __ RecordPosition(node->statement_pos()); 1429 if (FLAG_debug_info) __ RecordPosition(node->statement_pos());
1421 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1430 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1422 Visit(node->next()); 1431 Visit(node->next());
1423 } 1432 }
1424 1433
1425 // cond 1434 // cond
1426 __ bind(&entry); 1435 __ bind(&entry);
1427 switch (info) { 1436 switch (info) {
1428 case ALWAYS_TRUE: 1437 case ALWAYS_TRUE:
1429 CheckStack(); // TODO(1222600): ignore if body contains calls. 1438 CheckStack(); // TODO(1222600): ignore if body contains calls.
1430 __ b(&loop); 1439 loop.Jump();
1431 break; 1440 break;
1432 case ALWAYS_FALSE: 1441 case ALWAYS_FALSE:
1433 break; 1442 break;
1434 case DONT_KNOW: 1443 case DONT_KNOW:
1435 CheckStack(); // TODO(1222600): ignore if body contains calls. 1444 CheckStack(); // TODO(1222600): ignore if body contains calls.
1436 LoadCondition(node->cond(), 1445 LoadCondition(node->cond(),
1437 NOT_INSIDE_TYPEOF, 1446 NOT_INSIDE_TYPEOF,
1438 &loop, 1447 &loop,
1439 node->break_target(), 1448 node->break_target(),
1440 true); 1449 true);
1441 Branch(true, &loop); 1450 Branch(true, &loop);
1442 break; 1451 break;
1443 } 1452 }
1444 1453
1445 // exit 1454 // exit
1446 __ bind(node->break_target()); 1455 node->break_target()->Bind();
1447 } 1456 }
1448 1457
1449 1458
1450 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 1459 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1451 Comment cmnt(masm_, "[ ForInStatement"); 1460 Comment cmnt(masm_, "[ ForInStatement");
1452 if (FLAG_debug_info) RecordStatementPosition(node); 1461 if (FLAG_debug_info) RecordStatementPosition(node);
1453 1462
1454 // We keep stuff on the stack while the body is executing. 1463 // We keep stuff on the stack while the body is executing.
1455 // Record it, so that a break/continue crossing this statement 1464 // Record it, so that a break/continue crossing this statement
1456 // can restore the stack. 1465 // can restore the stack.
1457 const int kForInStackSize = 5 * kPointerSize; 1466 const int kForInStackSize = 5 * kPointerSize;
1458 break_stack_height_ += kForInStackSize; 1467 break_stack_height_ += kForInStackSize;
1459 node->set_break_stack_height(break_stack_height_); 1468 node->set_break_stack_height(break_stack_height_);
1469 node->break_target()->set_code_generator(this);
1470 node->continue_target()->set_code_generator(this);
1460 1471
1461 Label loop, next, entry, cleanup, exit, primitive, jsobject; 1472 Label loop, next, entry, cleanup, exit, primitive, jsobject;
1462 Label filter_key, end_del_check, fixed_array, non_string; 1473 Label filter_key, end_del_check, fixed_array, non_string;
1463 1474
1464 // Get the object to enumerate over (converted to JSObject). 1475 // Get the object to enumerate over (converted to JSObject).
1465 Load(node->enumerable()); 1476 Load(node->enumerable());
1466 __ pop(r0); 1477 __ pop(r0);
1467 1478
1468 // Both SpiderMonkey and kjs ignore null and undefined in contrast 1479 // Both SpiderMonkey and kjs ignore null and undefined in contrast
1469 // to the specification. 12.6.4 mandates a call to ToObject. 1480 // to the specification. 12.6.4 mandates a call to ToObject.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1537 __ mov(r0, Operand(Smi::FromInt(0))); // init index 1548 __ mov(r0, Operand(Smi::FromInt(0))); // init index
1538 __ push(r0); 1549 __ push(r0);
1539 1550
1540 __ b(&entry); 1551 __ b(&entry);
1541 1552
1542 // Body. 1553 // Body.
1543 __ bind(&loop); 1554 __ bind(&loop);
1544 Visit(node->body()); 1555 Visit(node->body());
1545 1556
1546 // Next. 1557 // Next.
1547 __ bind(node->continue_target()); 1558 node->continue_target()->Bind();
1548 __ bind(&next); 1559 __ bind(&next);
1549 __ pop(r0); 1560 __ pop(r0);
1550 __ add(r0, r0, Operand(Smi::FromInt(1))); 1561 __ add(r0, r0, Operand(Smi::FromInt(1)));
1551 __ push(r0); 1562 __ push(r0);
1552 1563
1553 // Condition. 1564 // Condition.
1554 __ bind(&entry); 1565 __ bind(&entry);
1555 1566
1556 // sp[0] : index 1567 // sp[0] : index
1557 // sp[1] : array/enum cache length 1568 // sp[1] : array/enum cache length
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 } 1629 }
1619 } 1630 }
1620 // Discard the i'th entry pushed above or else the remainder of the 1631 // Discard the i'th entry pushed above or else the remainder of the
1621 // reference, whichever is currently on top of the stack. 1632 // reference, whichever is currently on top of the stack.
1622 __ pop(); 1633 __ pop();
1623 CheckStack(); // TODO(1222600): ignore if body contains calls. 1634 CheckStack(); // TODO(1222600): ignore if body contains calls.
1624 __ jmp(&loop); 1635 __ jmp(&loop);
1625 1636
1626 // Cleanup. 1637 // Cleanup.
1627 __ bind(&cleanup); 1638 __ bind(&cleanup);
1628 __ bind(node->break_target()); 1639 node->break_target()->Bind();
1629 __ add(sp, sp, Operand(5 * kPointerSize)); 1640 __ add(sp, sp, Operand(5 * kPointerSize));
1630 1641
1631 // Exit. 1642 // Exit.
1632 __ bind(&exit); 1643 __ bind(&exit);
1633 1644
1634 break_stack_height_ -= kForInStackSize; 1645 break_stack_height_ -= kForInStackSize;
1635 } 1646 }
1636 1647
1637 1648
1638 void CodeGenerator::VisitTryCatch(TryCatch* node) { 1649 void CodeGenerator::VisitTryCatch(TryCatch* node) {
(...skipping 27 matching lines...) Expand all
1666 1677
1667 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1678 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1668 1679
1669 // Shadow the labels for all escapes from the try block, including 1680 // Shadow the labels for all escapes from the try block, including
1670 // returns. During shadowing, the original label is hidden as the 1681 // returns. During shadowing, the original label is hidden as the
1671 // LabelShadow and operations on the original actually affect the 1682 // LabelShadow and operations on the original actually affect the
1672 // shadowing label. 1683 // shadowing label.
1673 // 1684 //
1674 // We should probably try to unify the escaping labels and the return 1685 // We should probably try to unify the escaping labels and the return
1675 // label. 1686 // label.
1676 int nof_escapes = node->escaping_labels()->length(); 1687 int nof_escapes = node->escaping_targets()->length();
1677 List<LabelShadow*> shadows(1 + nof_escapes); 1688 List<ShadowTarget*> shadows(1 + nof_escapes);
1678 shadows.Add(new LabelShadow(&function_return_)); 1689 shadows.Add(new ShadowTarget(&function_return_));
1679 for (int i = 0; i < nof_escapes; i++) { 1690 for (int i = 0; i < nof_escapes; i++) {
1680 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); 1691 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
1681 } 1692 }
1682 1693
1683 // Generate code for the statements in the try block. 1694 // Generate code for the statements in the try block.
1684 VisitStatements(node->try_block()->statements()); 1695 VisitStatements(node->try_block()->statements());
1685 __ pop(r0); // Discard the result. 1696 __ pop(r0); // Discard the result.
1686 1697
1687 // Stop the introduced shadowing and count the number of required unlinks. 1698 // Stop the introduced shadowing and count the number of required unlinks.
1688 // After shadowing stops, the original labels are unshadowed and the 1699 // After shadowing stops, the original labels are unshadowed and the
1689 // LabelShadows represent the formerly shadowing labels. 1700 // LabelShadows represent the formerly shadowing labels.
1690 int nof_unlinks = 0; 1701 int nof_unlinks = 0;
(...skipping 13 matching lines...) Expand all
1704 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 1715 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
1705 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 1716 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
1706 // Code slot popped. 1717 // Code slot popped.
1707 if (nof_unlinks > 0) __ b(&exit); 1718 if (nof_unlinks > 0) __ b(&exit);
1708 1719
1709 // Generate unlink code for the (formerly) shadowing labels that have been 1720 // Generate unlink code for the (formerly) shadowing labels that have been
1710 // jumped to. 1721 // jumped to.
1711 for (int i = 0; i <= nof_escapes; i++) { 1722 for (int i = 0; i <= nof_escapes; i++) {
1712 if (shadows[i]->is_linked()) { 1723 if (shadows[i]->is_linked()) {
1713 // Unlink from try chain; 1724 // Unlink from try chain;
1714 __ bind(shadows[i]); 1725 shadows[i]->Bind();
1715 1726
1716 // Reload sp from the top handler, because some statements that we 1727 // Reload sp from the top handler, because some statements that we
1717 // break from (eg, for...in) may have left stuff on the stack. 1728 // break from (eg, for...in) may have left stuff on the stack.
1718 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 1729 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
1719 __ ldr(sp, MemOperand(r3)); 1730 __ ldr(sp, MemOperand(r3));
1720 1731
1721 __ ldr(r1, frame_->Element(kNextIndex)); 1732 __ ldr(r1, frame_->Element(kNextIndex));
1722 __ str(r1, MemOperand(r3)); 1733 __ str(r1, MemOperand(r3));
1723 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 1734 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
1724 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 1735 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
1725 // Code slot popped. 1736 // Code slot popped.
1726 1737
1727 __ b(shadows[i]->original_label()); 1738 shadows[i]->original_target()->Jump();
1728 } 1739 }
1729 } 1740 }
1730 1741
1731 __ bind(&exit); 1742 __ bind(&exit);
1732 } 1743 }
1733 1744
1734 1745
1735 void CodeGenerator::VisitTryFinally(TryFinally* node) { 1746 void CodeGenerator::VisitTryFinally(TryFinally* node) {
1736 Comment cmnt(masm_, "[ TryFinally"); 1747 Comment cmnt(masm_, "[ TryFinally");
1737 1748
(...skipping 16 matching lines...) Expand all
1754 __ bind(&try_block); 1765 __ bind(&try_block);
1755 1766
1756 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); 1767 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
1757 1768
1758 // Shadow the labels for all escapes from the try block, including 1769 // Shadow the labels for all escapes from the try block, including
1759 // returns. Shadowing hides the original label as the LabelShadow and 1770 // returns. Shadowing hides the original label as the LabelShadow and
1760 // operations on the original actually affect the shadowing label. 1771 // operations on the original actually affect the shadowing label.
1761 // 1772 //
1762 // We should probably try to unify the escaping labels and the return 1773 // We should probably try to unify the escaping labels and the return
1763 // label. 1774 // label.
1764 int nof_escapes = node->escaping_labels()->length(); 1775 int nof_escapes = node->escaping_targets()->length();
1765 List<LabelShadow*> shadows(1 + nof_escapes); 1776 List<ShadowTarget*> shadows(1 + nof_escapes);
1766 shadows.Add(new LabelShadow(&function_return_)); 1777 shadows.Add(new ShadowTarget(&function_return_));
1767 for (int i = 0; i < nof_escapes; i++) { 1778 for (int i = 0; i < nof_escapes; i++) {
1768 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); 1779 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
1769 } 1780 }
1770 1781
1771 // Generate code for the statements in the try block. 1782 // Generate code for the statements in the try block.
1772 VisitStatements(node->try_block()->statements()); 1783 VisitStatements(node->try_block()->statements());
1773 1784
1774 // Stop the introduced shadowing and count the number of required unlinks. 1785 // Stop the introduced shadowing and count the number of required unlinks.
1775 // After shadowing stops, the original labels are unshadowed and the 1786 // After shadowing stops, the original labels are unshadowed and the
1776 // LabelShadows represent the formerly shadowing labels. 1787 // LabelShadows represent the formerly shadowing labels.
1777 int nof_unlinks = 0; 1788 int nof_unlinks = 0;
1778 for (int i = 0; i <= nof_escapes; i++) { 1789 for (int i = 0; i <= nof_escapes; i++) {
1779 shadows[i]->StopShadowing(); 1790 shadows[i]->StopShadowing();
1780 if (shadows[i]->is_linked()) nof_unlinks++; 1791 if (shadows[i]->is_linked()) nof_unlinks++;
1781 } 1792 }
1782 1793
1783 // Set the state on the stack to FALLING. 1794 // Set the state on the stack to FALLING.
1784 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS 1795 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS
1785 __ push(r0); 1796 __ push(r0);
1786 __ mov(r2, Operand(Smi::FromInt(FALLING))); 1797 __ mov(r2, Operand(Smi::FromInt(FALLING)));
1787 if (nof_unlinks > 0) __ b(&unlink); 1798 if (nof_unlinks > 0) __ b(&unlink);
1788 1799
1789 // Generate code to set the state for the (formerly) shadowing labels that 1800 // Generate code to set the state for the (formerly) shadowing labels that
1790 // have been jumped to. 1801 // have been jumped to.
1791 for (int i = 0; i <= nof_escapes; i++) { 1802 for (int i = 0; i <= nof_escapes; i++) {
1792 if (shadows[i]->is_linked()) { 1803 if (shadows[i]->is_linked()) {
1793 __ bind(shadows[i]); 1804 shadows[i]->Bind();
1794 if (shadows[i]->original_label() == &function_return_) { 1805 if (shadows[i]->original_target() == &function_return_) {
1795 // If this label shadowed the function return, materialize the 1806 // If this label shadowed the function return, materialize the
1796 // return value on the stack. 1807 // return value on the stack.
1797 __ push(r0); 1808 __ push(r0);
1798 } else { 1809 } else {
1799 // Fake TOS for labels that shadowed breaks and continues. 1810 // Fake TOS for labels that shadowed breaks and continues.
1800 __ mov(r0, Operand(Factory::undefined_value())); 1811 __ mov(r0, Operand(Factory::undefined_value()));
1801 __ push(r0); 1812 __ push(r0);
1802 } 1813 }
1803 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); 1814 __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
1804 __ b(&unlink); 1815 __ b(&unlink);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1842 // Restore state and return value or faked TOS. 1853 // Restore state and return value or faked TOS.
1843 __ pop(r2); 1854 __ pop(r2);
1844 __ pop(r0); 1855 __ pop(r0);
1845 break_stack_height_ -= kFinallyStackSize; 1856 break_stack_height_ -= kFinallyStackSize;
1846 1857
1847 // Generate code to jump to the right destination for all used (formerly) 1858 // Generate code to jump to the right destination for all used (formerly)
1848 // shadowing labels. 1859 // shadowing labels.
1849 for (int i = 0; i <= nof_escapes; i++) { 1860 for (int i = 0; i <= nof_escapes; i++) {
1850 if (shadows[i]->is_bound()) { 1861 if (shadows[i]->is_bound()) {
1851 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); 1862 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
1852 if (shadows[i]->original_label() != &function_return_) { 1863 if (shadows[i]->original_target() != &function_return_) {
1853 Label next; 1864 Label next;
1854 __ b(ne, &next); 1865 __ b(ne, &next);
1855 __ b(shadows[i]->original_label()); 1866 shadows[i]->original_target()->Jump();
1856 __ bind(&next); 1867 __ bind(&next);
1857 } else { 1868 } else {
1858 __ b(eq, shadows[i]->original_label()); 1869 shadows[i]->original_target()->Branch(eq);
1859 } 1870 }
1860 } 1871 }
1861 } 1872 }
1862 1873
1863 // Check if we need to rethrow the exception. 1874 // Check if we need to rethrow the exception.
1864 __ cmp(r2, Operand(Smi::FromInt(THROWING))); 1875 __ cmp(r2, Operand(Smi::FromInt(THROWING)));
1865 __ b(ne, &exit); 1876 __ b(ne, &exit);
1866 1877
1867 // Rethrow exception. 1878 // Rethrow exception.
1868 __ push(r0); 1879 __ push(r0);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1908 1919
1909 void CodeGenerator::VisitFunctionBoilerplateLiteral( 1920 void CodeGenerator::VisitFunctionBoilerplateLiteral(
1910 FunctionBoilerplateLiteral* node) { 1921 FunctionBoilerplateLiteral* node) {
1911 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 1922 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
1912 InstantiateBoilerplate(node->boilerplate()); 1923 InstantiateBoilerplate(node->boilerplate());
1913 } 1924 }
1914 1925
1915 1926
1916 void CodeGenerator::VisitConditional(Conditional* node) { 1927 void CodeGenerator::VisitConditional(Conditional* node) {
1917 Comment cmnt(masm_, "[ Conditional"); 1928 Comment cmnt(masm_, "[ Conditional");
1918 Label then, else_, exit; 1929 JumpTarget then(this);
1930 JumpTarget else_(this);
1931 Label exit;
1919 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 1932 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
1920 Branch(false, &else_); 1933 Branch(false, &else_);
1921 __ bind(&then); 1934 then.Bind();
1922 Load(node->then_expression(), typeof_state()); 1935 Load(node->then_expression(), typeof_state());
1923 __ b(&exit); 1936 __ b(&exit);
1924 __ bind(&else_); 1937 else_.Bind();
1925 Load(node->else_expression(), typeof_state()); 1938 Load(node->else_expression(), typeof_state());
1926 __ bind(&exit); 1939 __ bind(&exit);
1927 } 1940 }
1928 1941
1929 1942
1930 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 1943 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
1931 if (slot->type() == Slot::LOOKUP) { 1944 if (slot->type() == Slot::LOOKUP) {
1932 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 1945 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
1933 1946
1934 // For now, just do a runtime call. 1947 // For now, just do a runtime call.
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after
2806 // produced by a && or || operator is not necessarily a boolean. 2819 // produced by a && or || operator is not necessarily a boolean.
2807 2820
2808 // NOTE: If the left hand side produces a materialized value (not in 2821 // NOTE: If the left hand side produces a materialized value (not in
2809 // the CC register), we force the right hand side to do the 2822 // the CC register), we force the right hand side to do the
2810 // same. This is necessary because we may have to branch to the exit 2823 // same. This is necessary because we may have to branch to the exit
2811 // after evaluating the left hand side (due to the shortcut 2824 // after evaluating the left hand side (due to the shortcut
2812 // semantics), but the compiler must (statically) know if the result 2825 // semantics), but the compiler must (statically) know if the result
2813 // of compiling the binary operation is materialized or not. 2826 // of compiling the binary operation is materialized or not.
2814 2827
2815 if (op == Token::AND) { 2828 if (op == Token::AND) {
2816 Label is_true; 2829 JumpTarget is_true(this);
2817 LoadCondition(node->left(), 2830 LoadCondition(node->left(),
2818 NOT_INSIDE_TYPEOF, 2831 NOT_INSIDE_TYPEOF,
2819 &is_true, 2832 &is_true,
2820 false_target(), 2833 false_target(),
2821 false); 2834 false);
2822 if (has_cc()) { 2835 if (has_cc()) {
2823 Branch(false, false_target()); 2836 Branch(false, false_target());
2824 2837
2825 // Evaluate right side expression. 2838 // Evaluate right side expression.
2826 __ bind(&is_true); 2839 is_true.Bind();
2827 LoadCondition(node->right(), 2840 LoadCondition(node->right(),
2828 NOT_INSIDE_TYPEOF, 2841 NOT_INSIDE_TYPEOF,
2829 true_target(), 2842 true_target(),
2830 false_target(), 2843 false_target(),
2831 false); 2844 false);
2832 2845
2833 } else { 2846 } else {
2834 Label pop_and_continue, exit; 2847 JumpTarget pop_and_continue(this);
2848 JumpTarget exit(this);
2835 2849
2836 __ ldr(r0, frame_->Top()); // dup the stack top 2850 __ ldr(r0, frame_->Top()); // dup the stack top
2837 __ push(r0); 2851 __ push(r0);
2838 // Avoid popping the result if it converts to 'false' using the 2852 // Avoid popping the result if it converts to 'false' using the
2839 // standard ToBoolean() conversion as described in ECMA-262, 2853 // standard ToBoolean() conversion as described in ECMA-262,
2840 // section 9.2, page 30. 2854 // section 9.2, page 30.
2841 ToBoolean(&pop_and_continue, &exit); 2855 ToBoolean(&pop_and_continue, &exit);
2842 Branch(false, &exit); 2856 Branch(false, &exit);
2843 2857
2844 // Pop the result of evaluating the first part. 2858 // Pop the result of evaluating the first part.
2845 __ bind(&pop_and_continue); 2859 pop_and_continue.Bind();
2846 __ pop(r0); 2860 __ pop(r0);
2847 2861
2848 // Evaluate right side expression. 2862 // Evaluate right side expression.
2849 __ bind(&is_true); 2863 is_true.Bind();
2850 Load(node->right()); 2864 Load(node->right());
2851 2865
2852 // Exit (always with a materialized value). 2866 // Exit (always with a materialized value).
2853 __ bind(&exit); 2867 exit.Bind();
2854 } 2868 }
2855 2869
2856 } else if (op == Token::OR) { 2870 } else if (op == Token::OR) {
2857 Label is_false; 2871 JumpTarget is_false(this);
2858 LoadCondition(node->left(), 2872 LoadCondition(node->left(),
2859 NOT_INSIDE_TYPEOF, 2873 NOT_INSIDE_TYPEOF,
2860 true_target(), 2874 true_target(),
2861 &is_false, 2875 &is_false,
2862 false); 2876 false);
2863 if (has_cc()) { 2877 if (has_cc()) {
2864 Branch(true, true_target()); 2878 Branch(true, true_target());
2865 2879
2866 // Evaluate right side expression. 2880 // Evaluate right side expression.
2867 __ bind(&is_false); 2881 is_false.Bind();
2868 LoadCondition(node->right(), 2882 LoadCondition(node->right(),
2869 NOT_INSIDE_TYPEOF, 2883 NOT_INSIDE_TYPEOF,
2870 true_target(), 2884 true_target(),
2871 false_target(), 2885 false_target(),
2872 false); 2886 false);
2873 2887
2874 } else { 2888 } else {
2875 Label pop_and_continue, exit; 2889 JumpTarget pop_and_continue(this);
2890 JumpTarget exit(this);
2876 2891
2877 __ ldr(r0, frame_->Top()); 2892 __ ldr(r0, frame_->Top());
2878 __ push(r0); 2893 __ push(r0);
2879 // Avoid popping the result if it converts to 'true' using the 2894 // Avoid popping the result if it converts to 'true' using the
2880 // standard ToBoolean() conversion as described in ECMA-262, 2895 // standard ToBoolean() conversion as described in ECMA-262,
2881 // section 9.2, page 30. 2896 // section 9.2, page 30.
2882 ToBoolean(&exit, &pop_and_continue); 2897 ToBoolean(&exit, &pop_and_continue);
2883 Branch(true, &exit); 2898 Branch(true, &exit);
2884 2899
2885 // Pop the result of evaluating the first part. 2900 // Pop the result of evaluating the first part.
2886 __ bind(&pop_and_continue); 2901 pop_and_continue.Bind();
2887 __ pop(r0); 2902 __ pop(r0);
2888 2903
2889 // Evaluate right side expression. 2904 // Evaluate right side expression.
2890 __ bind(&is_false); 2905 is_false.Bind();
2891 Load(node->right()); 2906 Load(node->right());
2892 2907
2893 // Exit (always with a materialized value). 2908 // Exit (always with a materialized value).
2894 __ bind(&exit); 2909 exit.Bind();
2895 } 2910 }
2896 2911
2897 } else { 2912 } else {
2898 // Optimize for the case where (at least) one of the expressions 2913 // Optimize for the case where (at least) one of the expressions
2899 // is a literal small integer. 2914 // is a literal small integer.
2900 Literal* lliteral = node->left()->AsLiteral(); 2915 Literal* lliteral = node->left()->AsLiteral();
2901 Literal* rliteral = node->right()->AsLiteral(); 2916 Literal* rliteral = node->right()->AsLiteral();
2902 2917
2903 if (rliteral != NULL && rliteral->handle()->IsSmi()) { 2918 if (rliteral != NULL && rliteral->handle()->IsSmi()) {
2904 Load(node->left()); 2919 Load(node->left());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2953 // non-strict comparisons. 2968 // non-strict comparisons.
2954 if (op != Token::EQ_STRICT) { 2969 if (op != Token::EQ_STRICT) {
2955 __ b(eq, &exit); 2970 __ b(eq, &exit);
2956 __ cmp(r0, Operand(Factory::undefined_value())); 2971 __ cmp(r0, Operand(Factory::undefined_value()));
2957 2972
2958 // NOTE: it can be undetectable object. 2973 // NOTE: it can be undetectable object.
2959 __ b(eq, &exit); 2974 __ b(eq, &exit);
2960 __ tst(r0, Operand(kSmiTagMask)); 2975 __ tst(r0, Operand(kSmiTagMask));
2961 2976
2962 __ b(ne, &undetectable); 2977 __ b(ne, &undetectable);
2963 __ b(false_target()); 2978 false_target()->Jump();
2964 2979
2965 __ bind(&undetectable); 2980 __ bind(&undetectable);
2966 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2981 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2967 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 2982 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
2968 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 2983 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
2969 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 2984 __ cmp(r2, Operand(1 << Map::kIsUndetectable));
2970 } 2985 }
2971 2986
2972 __ bind(&exit); 2987 __ bind(&exit);
2973 2988
(...skipping 13 matching lines...) Expand all
2987 (right->AsLiteral() != NULL && 3002 (right->AsLiteral() != NULL &&
2988 right->AsLiteral()->handle()->IsString())) { 3003 right->AsLiteral()->handle()->IsString())) {
2989 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 3004 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
2990 3005
2991 // Load the operand, move it to register r1. 3006 // Load the operand, move it to register r1.
2992 LoadTypeofExpression(operation->expression()); 3007 LoadTypeofExpression(operation->expression());
2993 __ pop(r1); 3008 __ pop(r1);
2994 3009
2995 if (check->Equals(Heap::number_symbol())) { 3010 if (check->Equals(Heap::number_symbol())) {
2996 __ tst(r1, Operand(kSmiTagMask)); 3011 __ tst(r1, Operand(kSmiTagMask));
2997 __ b(eq, true_target()); 3012 true_target()->Branch(eq);
2998 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3013 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
2999 __ cmp(r1, Operand(Factory::heap_number_map())); 3014 __ cmp(r1, Operand(Factory::heap_number_map()));
3000 cc_reg_ = eq; 3015 cc_reg_ = eq;
3001 3016
3002 } else if (check->Equals(Heap::string_symbol())) { 3017 } else if (check->Equals(Heap::string_symbol())) {
3003 __ tst(r1, Operand(kSmiTagMask)); 3018 __ tst(r1, Operand(kSmiTagMask));
3004 __ b(eq, false_target()); 3019 false_target()->Branch(eq);
3005 3020
3006 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3021 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
3007 3022
3008 // NOTE: it might be an undetectable string object 3023 // NOTE: it might be an undetectable string object
3009 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 3024 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
3010 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 3025 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
3011 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 3026 __ cmp(r2, Operand(1 << Map::kIsUndetectable));
3012 __ b(eq, false_target()); 3027 false_target()->Branch(eq);
3013 3028
3014 __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3029 __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3015 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE)); 3030 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
3016 cc_reg_ = lt; 3031 cc_reg_ = lt;
3017 3032
3018 } else if (check->Equals(Heap::boolean_symbol())) { 3033 } else if (check->Equals(Heap::boolean_symbol())) {
3019 __ cmp(r1, Operand(Factory::true_value())); 3034 __ cmp(r1, Operand(Factory::true_value()));
3020 __ b(eq, true_target()); 3035 true_target()->Branch(eq);
3021 __ cmp(r1, Operand(Factory::false_value())); 3036 __ cmp(r1, Operand(Factory::false_value()));
3022 cc_reg_ = eq; 3037 cc_reg_ = eq;
3023 3038
3024 } else if (check->Equals(Heap::undefined_symbol())) { 3039 } else if (check->Equals(Heap::undefined_symbol())) {
3025 __ cmp(r1, Operand(Factory::undefined_value())); 3040 __ cmp(r1, Operand(Factory::undefined_value()));
3026 __ b(eq, true_target()); 3041 true_target()->Branch(eq);
3027 3042
3028 __ tst(r1, Operand(kSmiTagMask)); 3043 __ tst(r1, Operand(kSmiTagMask));
3029 __ b(eq, false_target()); 3044 false_target()->Branch(eq);
3030 3045
3031 // NOTE: it can be undetectable object. 3046 // NOTE: it can be undetectable object.
3032 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3047 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
3033 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 3048 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
3034 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 3049 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
3035 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 3050 __ cmp(r2, Operand(1 << Map::kIsUndetectable));
3036 3051
3037 cc_reg_ = eq; 3052 cc_reg_ = eq;
3038 3053
3039 } else if (check->Equals(Heap::function_symbol())) { 3054 } else if (check->Equals(Heap::function_symbol())) {
3040 __ tst(r1, Operand(kSmiTagMask)); 3055 __ tst(r1, Operand(kSmiTagMask));
3041 __ b(eq, false_target()); 3056 false_target()->Branch(eq);
3042 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3057 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
3043 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3058 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3044 __ cmp(r1, Operand(JS_FUNCTION_TYPE)); 3059 __ cmp(r1, Operand(JS_FUNCTION_TYPE));
3045 cc_reg_ = eq; 3060 cc_reg_ = eq;
3046 3061
3047 } else if (check->Equals(Heap::object_symbol())) { 3062 } else if (check->Equals(Heap::object_symbol())) {
3048 __ tst(r1, Operand(kSmiTagMask)); 3063 __ tst(r1, Operand(kSmiTagMask));
3049 __ b(eq, false_target()); 3064 false_target()->Branch(eq);
3050 3065
3051 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3066 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
3052 __ cmp(r1, Operand(Factory::null_value())); 3067 __ cmp(r1, Operand(Factory::null_value()));
3053 __ b(eq, true_target()); 3068 true_target()->Branch(eq);
3054 3069
3055 // NOTE: it might be an undetectable object. 3070 // NOTE: it might be an undetectable object.
3056 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 3071 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
3057 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 3072 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
3058 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 3073 __ cmp(r1, Operand(1 << Map::kIsUndetectable));
3059 __ b(eq, false_target()); 3074 false_target()->Branch(eq);
3060 3075
3061 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 3076 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
3062 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); 3077 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
3063 __ b(lt, false_target()); 3078 false_target()->Branch(lt);
3064 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); 3079 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE));
3065 cc_reg_ = le; 3080 cc_reg_ = le;
3066 3081
3067 } else { 3082 } else {
3068 // Uncommon case: Typeof testing against a string literal that 3083 // Uncommon case: Typeof testing against a string literal that
3069 // is never returned from the typeof operator. 3084 // is never returned from the typeof operator.
3070 __ b(false_target()); 3085 false_target()->Jump();
3071 } 3086 }
3072 return; 3087 return;
3073 } 3088 }
3074 3089
3075 Load(left); 3090 Load(left);
3076 Load(right); 3091 Load(right);
3077 switch (op) { 3092 switch (op) {
3078 case Token::EQ: 3093 case Token::EQ:
3079 Comparison(eq, false); 3094 Comparison(eq, false);
3080 break; 3095 break;
(...skipping 1167 matching lines...) Expand 10 before | Expand all | Expand 10 after
4248 // Slow-case: Non-function called. 4263 // Slow-case: Non-function called.
4249 __ bind(&slow); 4264 __ bind(&slow);
4250 __ mov(r0, Operand(argc_)); // Setup the number of arguments. 4265 __ mov(r0, Operand(argc_)); // Setup the number of arguments.
4251 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); 4266 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS);
4252 } 4267 }
4253 4268
4254 4269
4255 #undef __ 4270 #undef __
4256 4271
4257 } } // namespace v8::internal 4272 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.h ('k') | src/codegen-ia32.cc » ('j') | src/jump-target.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698