| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 112 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 113 int num_parameters = function_->scope()->num_parameters(); | 113 int num_parameters = function_->scope()->num_parameters(); |
| 114 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); | 114 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); |
| 115 __ Jump(lr); | 115 __ Jump(lr); |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 | 119 |
| 120 void FastCodeGenerator::Move(Location destination, Slot* source) { | 120 void FastCodeGenerator::Move(Location destination, Slot* source) { |
| 121 switch (destination.type()) { | 121 switch (destination.type()) { |
| 122 case Location::NOWHERE: | 122 case Location::UNINITIALIZED: |
| 123 UNREACHABLE(); |
| 124 case Location::EFFECT: |
| 123 break; | 125 break; |
| 124 case Location::TEMP: | 126 case Location::VALUE: |
| 125 __ ldr(ip, MemOperand(fp, SlotOffset(source))); | 127 __ ldr(ip, MemOperand(fp, SlotOffset(source))); |
| 126 __ push(ip); | 128 __ push(ip); |
| 127 break; | 129 break; |
| 128 } | 130 } |
| 129 } | 131 } |
| 130 | 132 |
| 131 | 133 |
| 132 void FastCodeGenerator::Move(Location destination, Literal* expr) { | 134 void FastCodeGenerator::Move(Location destination, Literal* expr) { |
| 133 switch (destination.type()) { | 135 switch (destination.type()) { |
| 134 case Location::NOWHERE: | 136 case Location::UNINITIALIZED: |
| 137 UNREACHABLE(); |
| 138 case Location::EFFECT: |
| 135 break; | 139 break; |
| 136 case Location::TEMP: | 140 case Location::VALUE: |
| 137 __ mov(ip, Operand(expr->handle())); | 141 __ mov(ip, Operand(expr->handle())); |
| 138 __ push(ip); | 142 __ push(ip); |
| 139 break; | 143 break; |
| 140 } | 144 } |
| 141 } | 145 } |
| 142 | 146 |
| 143 | 147 |
| 144 void FastCodeGenerator::Move(Slot* destination, Location source) { | 148 void FastCodeGenerator::Move(Slot* destination, Location source) { |
| 145 switch (source.type()) { | 149 switch (source.type()) { |
| 146 case Location::NOWHERE: | 150 case Location::UNINITIALIZED: // Fall through. |
| 151 case Location::EFFECT: |
| 147 UNREACHABLE(); | 152 UNREACHABLE(); |
| 148 case Location::TEMP: | 153 case Location::VALUE: |
| 149 __ pop(ip); | 154 __ pop(ip); |
| 150 __ str(ip, MemOperand(fp, SlotOffset(destination))); | 155 __ str(ip, MemOperand(fp, SlotOffset(destination))); |
| 151 break; | 156 break; |
| 152 } | 157 } |
| 153 } | 158 } |
| 154 | 159 |
| 155 | 160 |
| 156 void FastCodeGenerator::DropAndMove(Location destination, Register source) { | 161 void FastCodeGenerator::DropAndMove(Location destination, Register source) { |
| 157 switch (destination.type()) { | 162 switch (destination.type()) { |
| 158 case Location::NOWHERE: | 163 case Location::UNINITIALIZED: |
| 164 UNREACHABLE(); |
| 165 case Location::EFFECT: |
| 159 __ pop(); | 166 __ pop(); |
| 160 break; | 167 break; |
| 161 case Location::TEMP: | 168 case Location::VALUE: |
| 162 __ str(source, MemOperand(sp)); | 169 __ str(source, MemOperand(sp)); |
| 163 break; | 170 break; |
| 164 } | 171 } |
| 165 } | 172 } |
| 166 | 173 |
| 167 | 174 |
| 168 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 175 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 169 // Call the runtime to declare the globals. | 176 // Call the runtime to declare the globals. |
| 170 // The context is the first argument. | 177 // The context is the first argument. |
| 171 __ mov(r1, Operand(pairs)); | 178 __ mov(r1, Operand(pairs)); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 239 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 233 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 240 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 234 DropAndMove(expr->location(), r0); | 241 DropAndMove(expr->location(), r0); |
| 235 } else { | 242 } else { |
| 236 Comment cmnt(masm_, "Stack slot"); | 243 Comment cmnt(masm_, "Stack slot"); |
| 237 Move(expr->location(), rewrite->AsSlot()); | 244 Move(expr->location(), rewrite->AsSlot()); |
| 238 } | 245 } |
| 239 } | 246 } |
| 240 | 247 |
| 241 | 248 |
| 249 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 250 Comment cmnt(masm_, "[ RegExp Literal"); |
| 251 Label done; |
| 252 // Registers will be used as follows: |
| 253 // r4 = JS function, literals array |
| 254 // r3 = literal index |
| 255 // r2 = RegExp pattern |
| 256 // r1 = RegExp flags |
| 257 // r0 = temp + return value (RegExp literal) |
| 258 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 259 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
| 260 int literal_offset = |
| 261 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 262 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
| 263 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 264 __ cmp(r0, ip); |
| 265 __ b(ne, &done); |
| 266 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
| 267 __ mov(r2, Operand(expr->pattern())); |
| 268 __ mov(r1, Operand(expr->flags())); |
| 269 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
| 270 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 271 __ bind(&done); |
| 272 Move(expr->location(), r0); |
| 273 } |
| 274 |
| 275 |
| 242 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 276 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 243 Comment cmnt(masm_, "[ ObjectLiteral"); | 277 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 244 Label boilerplate_exists; | 278 Label boilerplate_exists; |
| 245 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 279 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 246 // r2 = literal array (0). | 280 // r2 = literal array (0). |
| 247 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 281 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
| 248 int literal_offset = | 282 int literal_offset = |
| 249 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 283 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 250 __ ldr(r0, FieldMemOperand(r2, literal_offset)); | 284 __ ldr(r0, FieldMemOperand(r2, literal_offset)); |
| 251 // Check whether we need to materialize the object literal boilerplate. | 285 // Check whether we need to materialize the object literal boilerplate. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 277 ObjectLiteral::Property* property = expr->properties()->at(i); | 311 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 278 if (property->IsCompileTimeValue()) continue; | 312 if (property->IsCompileTimeValue()) continue; |
| 279 | 313 |
| 280 Literal* key = property->key(); | 314 Literal* key = property->key(); |
| 281 Expression* value = property->value(); | 315 Expression* value = property->value(); |
| 282 if (!result_saved) { | 316 if (!result_saved) { |
| 283 __ push(r0); // Save result on stack | 317 __ push(r0); // Save result on stack |
| 284 result_saved = true; | 318 result_saved = true; |
| 285 } | 319 } |
| 286 switch (property->kind()) { | 320 switch (property->kind()) { |
| 287 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // fall through | 321 case ObjectLiteral::Property::CONSTANT: |
| 322 UNREACHABLE(); |
| 323 |
| 324 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // Fall through. |
| 288 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 325 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 289 case ObjectLiteral::Property::COMPUTED: // fall through | 326 case ObjectLiteral::Property::COMPUTED: |
| 327 if (key->handle()->IsSymbol()) { |
| 328 Visit(value); |
| 329 Move(r0, value->location()); |
| 330 __ mov(r2, Operand(key->handle())); |
| 331 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 332 __ Call(ic, RelocInfo::CODE_TARGET); |
| 333 // StoreIC leaves the receiver on the stack. |
| 334 break; |
| 335 } |
| 336 // Fall through. |
| 337 |
| 290 case ObjectLiteral::Property::PROTOTYPE: | 338 case ObjectLiteral::Property::PROTOTYPE: |
| 291 __ push(r0); | 339 __ push(r0); |
| 292 Visit(key); | 340 Visit(key); |
| 293 ASSERT(key->location().is_temporary()); | 341 ASSERT(key->location().is_value()); |
| 294 Visit(value); | 342 Visit(value); |
| 295 ASSERT(value->location().is_temporary()); | 343 ASSERT(value->location().is_value()); |
| 296 __ CallRuntime(Runtime::kSetProperty, 3); | 344 __ CallRuntime(Runtime::kSetProperty, 3); |
| 297 __ ldr(r0, MemOperand(sp)); // Restore result into r0 | 345 __ ldr(r0, MemOperand(sp)); // Restore result into r0 |
| 298 break; | 346 break; |
| 299 case ObjectLiteral::Property::SETTER: // fall through | 347 |
| 300 case ObjectLiteral::Property::GETTER: | 348 case ObjectLiteral::Property::GETTER: // Fall through. |
| 349 case ObjectLiteral::Property::SETTER: |
| 301 __ push(r0); | 350 __ push(r0); |
| 302 Visit(key); | 351 Visit(key); |
| 303 ASSERT(key->location().is_temporary()); | 352 ASSERT(key->location().is_value()); |
| 304 __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? | 353 __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? |
| 305 Smi::FromInt(1) : | 354 Smi::FromInt(1) : |
| 306 Smi::FromInt(0))); | 355 Smi::FromInt(0))); |
| 307 __ push(r1); | 356 __ push(r1); |
| 308 Visit(value); | 357 Visit(value); |
| 309 ASSERT(value->location().is_temporary()); | 358 ASSERT(value->location().is_value()); |
| 310 __ CallRuntime(Runtime::kDefineAccessor, 4); | 359 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 311 __ ldr(r0, MemOperand(sp)); // Restore result into r0 | 360 __ ldr(r0, MemOperand(sp)); // Restore result into r0 |
| 312 break; | 361 break; |
| 313 default: UNREACHABLE(); | |
| 314 } | 362 } |
| 315 } | 363 } |
| 316 switch (expr->location().type()) { | 364 switch (expr->location().type()) { |
| 317 case Location::NOWHERE: | 365 case Location::UNINITIALIZED: |
| 366 UNREACHABLE(); |
| 367 case Location::EFFECT: |
| 318 if (result_saved) __ pop(); | 368 if (result_saved) __ pop(); |
| 319 break; | 369 break; |
| 320 case Location::TEMP: | 370 case Location::VALUE: |
| 321 if (!result_saved) __ push(r0); | 371 if (!result_saved) __ push(r0); |
| 322 break; | 372 break; |
| 323 } | 373 } |
| 324 } | 374 } |
| 325 | 375 |
| 326 | 376 |
| 327 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | |
| 328 Comment cmnt(masm_, "[ RegExp Literal"); | |
| 329 Label done; | |
| 330 // Registers will be used as follows: | |
| 331 // r4 = JS function, literals array | |
| 332 // r3 = literal index | |
| 333 // r2 = RegExp pattern | |
| 334 // r1 = RegExp flags | |
| 335 // r0 = temp + return value (RegExp literal) | |
| 336 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | |
| 337 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | |
| 338 int literal_offset = | |
| 339 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | |
| 340 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | |
| 341 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | |
| 342 __ cmp(r0, ip); | |
| 343 __ b(ne, &done); | |
| 344 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | |
| 345 __ mov(r2, Operand(expr->pattern())); | |
| 346 __ mov(r1, Operand(expr->flags())); | |
| 347 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | |
| 348 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | |
| 349 __ bind(&done); | |
| 350 Move(expr->location(), r0); | |
| 351 } | |
| 352 | |
| 353 | |
| 354 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 377 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 355 Comment cmnt(masm_, "[ ArrayLiteral"); | 378 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 356 Label make_clone; | 379 Label make_clone; |
| 357 | 380 |
| 358 // Fetch the function's literals array. | 381 // Fetch the function's literals array. |
| 359 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 382 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 360 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 383 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
| 361 // Check if the literal's boilerplate has been instantiated. | 384 // Check if the literal's boilerplate has been instantiated. |
| 362 int offset = | 385 int offset = |
| 363 FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); | 386 FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 393 if (subexpr->AsLiteral() != NULL || | 416 if (subexpr->AsLiteral() != NULL || |
| 394 CompileTimeValue::IsCompileTimeValue(subexpr)) { | 417 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
| 395 continue; | 418 continue; |
| 396 } | 419 } |
| 397 | 420 |
| 398 if (!result_saved) { | 421 if (!result_saved) { |
| 399 __ push(r0); | 422 __ push(r0); |
| 400 result_saved = true; | 423 result_saved = true; |
| 401 } | 424 } |
| 402 Visit(subexpr); | 425 Visit(subexpr); |
| 403 ASSERT(subexpr->location().is_temporary()); | 426 ASSERT(subexpr->location().is_value()); |
| 404 | 427 |
| 405 // Store the subexpression value in the array's elements. | 428 // Store the subexpression value in the array's elements. |
| 406 __ pop(r0); // Subexpression value. | 429 __ pop(r0); // Subexpression value. |
| 407 __ ldr(r1, MemOperand(sp)); // Copy of array literal. | 430 __ ldr(r1, MemOperand(sp)); // Copy of array literal. |
| 408 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 431 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| 409 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 432 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 410 __ str(r0, FieldMemOperand(r1, offset)); | 433 __ str(r0, FieldMemOperand(r1, offset)); |
| 411 | 434 |
| 412 // Update the write barrier for the array store with r0 as the scratch | 435 // Update the write barrier for the array store with r0 as the scratch |
| 413 // register. | 436 // register. |
| 414 __ mov(r2, Operand(offset)); | 437 __ mov(r2, Operand(offset)); |
| 415 __ RecordWrite(r1, r2, r0); | 438 __ RecordWrite(r1, r2, r0); |
| 416 } | 439 } |
| 417 | 440 |
| 418 switch (expr->location().type()) { | 441 switch (expr->location().type()) { |
| 419 case Location::NOWHERE: | 442 case Location::UNINITIALIZED: |
| 443 UNREACHABLE(); |
| 444 case Location::EFFECT: |
| 420 if (result_saved) __ pop(); | 445 if (result_saved) __ pop(); |
| 421 break; | 446 break; |
| 422 case Location::TEMP: | 447 case Location::VALUE: |
| 423 if (!result_saved) __ push(r0); | 448 if (!result_saved) __ push(r0); |
| 424 break; | 449 break; |
| 425 } | 450 } |
| 426 } | 451 } |
| 427 | 452 |
| 428 | 453 |
| 429 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 454 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
| 430 Comment cmnt(masm_, "[ Assignment"); | 455 Comment cmnt(masm_, "[ Assignment"); |
| 431 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 456 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
| 432 | 457 |
| 433 // Left-hand side can only be a global or a (parameter or local) slot. | 458 // Left-hand side can only be a global or a (parameter or local) slot. |
| 434 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 459 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 435 ASSERT(var != NULL); | 460 ASSERT(var != NULL); |
| 436 ASSERT(var->is_global() || var->slot() != NULL); | 461 ASSERT(var->is_global() || var->slot() != NULL); |
| 437 | 462 |
| 438 Expression* rhs = expr->value(); | 463 Expression* rhs = expr->value(); |
| 439 Location destination = expr->location(); | 464 Location destination = expr->location(); |
| 440 if (var->is_global()) { | 465 if (var->is_global()) { |
| 441 // Assignment to a global variable, use inline caching. Right-hand-side | 466 // Assignment to a global variable, use inline caching. Right-hand-side |
| 442 // value is passed in r0, variable name in r2, and the global object on | 467 // value is passed in r0, variable name in r2, and the global object on |
| 443 // the stack. | 468 // the stack. |
| 444 | 469 |
| 445 // Code for the right-hand-side expression depends on its type. | 470 // Code for the right-hand-side expression depends on its type. |
| 446 if (rhs->AsLiteral() != NULL) { | 471 if (rhs->AsLiteral() != NULL) { |
| 447 __ mov(r0, Operand(rhs->AsLiteral()->handle())); | 472 __ mov(r0, Operand(rhs->AsLiteral()->handle())); |
| 448 } else { | 473 } else { |
| 449 ASSERT(rhs->location().is_temporary()); | 474 ASSERT(rhs->location().is_value()); |
| 450 Visit(rhs); | 475 Visit(rhs); |
| 451 __ pop(r0); | 476 __ pop(r0); |
| 452 } | 477 } |
| 453 __ mov(r2, Operand(var->name())); | 478 __ mov(r2, Operand(var->name())); |
| 454 __ ldr(ip, CodeGenerator::GlobalObject()); | 479 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 455 __ push(ip); | 480 __ push(ip); |
| 456 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 481 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 457 __ Call(ic, RelocInfo::CODE_TARGET); | 482 __ Call(ic, RelocInfo::CODE_TARGET); |
| 458 // Overwrite the global object on the stack with the result if needed. | 483 // Overwrite the global object on the stack with the result if needed. |
| 459 DropAndMove(expr->location(), r0); | 484 DropAndMove(expr->location(), r0); |
| 460 } else { | 485 } else { |
| 461 // Local or parameter assignment. | 486 // Local or parameter assignment. |
| 462 | 487 |
| 463 // Code for the right-hand side expression depends on its type. | 488 // Code for the right-hand side expression depends on its type. |
| 464 if (rhs->AsLiteral() != NULL) { | 489 if (rhs->AsLiteral() != NULL) { |
| 465 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 490 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
| 466 // discarded result. Always perform the assignment. | 491 // discarded result. Always perform the assignment. |
| 467 __ mov(ip, Operand(rhs->AsLiteral()->handle())); | 492 __ mov(ip, Operand(rhs->AsLiteral()->handle())); |
| 468 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | 493 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
| 469 Move(expr->location(), ip); | 494 Move(expr->location(), ip); |
| 470 } else { | 495 } else { |
| 471 ASSERT(rhs->location().is_temporary()); | 496 ASSERT(rhs->location().is_value()); |
| 472 Visit(rhs); | 497 Visit(rhs); |
| 473 // Load right-hand side into ip. | 498 // Load right-hand side into ip. |
| 474 switch (expr->location().type()) { | 499 switch (expr->location().type()) { |
| 475 case Location::NOWHERE: | 500 case Location::UNINITIALIZED: |
| 501 UNREACHABLE(); |
| 502 case Location::EFFECT: |
| 476 // Case 'var = temp'. Discard right-hand-side temporary. | 503 // Case 'var = temp'. Discard right-hand-side temporary. |
| 477 __ pop(ip); | 504 __ pop(ip); |
| 478 break; | 505 break; |
| 479 case Location::TEMP: | 506 case Location::VALUE: |
| 480 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 507 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side |
| 481 // temporary on the stack. | 508 // temporary on the stack. |
| 482 __ ldr(ip, MemOperand(sp)); | 509 __ ldr(ip, MemOperand(sp)); |
| 483 break; | 510 break; |
| 484 } | 511 } |
| 485 // Do the slot assignment. | 512 // Do the slot assignment. |
| 486 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | 513 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
| 487 } | 514 } |
| 488 } | 515 } |
| 489 } | 516 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 515 Visit(expr->key()); | 542 Visit(expr->key()); |
| 516 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 543 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 517 __ Call(ic, RelocInfo::CODE_TARGET); | 544 __ Call(ic, RelocInfo::CODE_TARGET); |
| 518 // By emitting a nop we make sure that we do not have a "test eax,..." | 545 // By emitting a nop we make sure that we do not have a "test eax,..." |
| 519 // instruction after the call it is treated specially by the LoadIC code. | 546 // instruction after the call it is treated specially by the LoadIC code. |
| 520 __ nop(); | 547 __ nop(); |
| 521 // Drop key and receiver left on the stack by IC. | 548 // Drop key and receiver left on the stack by IC. |
| 522 __ pop(); | 549 __ pop(); |
| 523 } | 550 } |
| 524 switch (expr->location().type()) { | 551 switch (expr->location().type()) { |
| 525 case Location::TEMP: | 552 case Location::UNINITIALIZED: |
| 553 UNREACHABLE(); |
| 554 case Location::VALUE: |
| 526 __ str(r0, MemOperand(sp)); | 555 __ str(r0, MemOperand(sp)); |
| 527 break; | 556 break; |
| 528 case Location::NOWHERE: | 557 case Location::EFFECT: |
| 529 __ pop(); | 558 __ pop(); |
| 530 } | 559 } |
| 531 } | 560 } |
| 532 | 561 |
| 533 | 562 |
| 534 void FastCodeGenerator::VisitCall(Call* expr) { | 563 void FastCodeGenerator::VisitCall(Call* expr) { |
| 535 Comment cmnt(masm_, "[ Call"); | 564 Comment cmnt(masm_, "[ Call"); |
| 536 Expression* fun = expr->expression(); | 565 Expression* fun = expr->expression(); |
| 537 ZoneList<Expression*>* args = expr->arguments(); | 566 ZoneList<Expression*>* args = expr->arguments(); |
| 538 Variable* var = fun->AsVariableProxy()->AsVariable(); | 567 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 539 ASSERT(var != NULL && !var->is_this() && var->is_global()); | 568 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
| 540 ASSERT(!var->is_possibly_eval()); | 569 ASSERT(!var->is_possibly_eval()); |
| 541 | 570 |
| 542 __ mov(r1, Operand(var->name())); | 571 __ mov(r1, Operand(var->name())); |
| 543 // Push global object as receiver. | 572 // Push global object as receiver. |
| 544 __ ldr(r0, CodeGenerator::GlobalObject()); | 573 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 545 __ stm(db_w, sp, r1.bit() | r0.bit()); | 574 __ stm(db_w, sp, r1.bit() | r0.bit()); |
| 546 int arg_count = args->length(); | 575 int arg_count = args->length(); |
| 547 for (int i = 0; i < arg_count; i++) { | 576 for (int i = 0; i < arg_count; i++) { |
| 548 Visit(args->at(i)); | 577 Visit(args->at(i)); |
| 549 ASSERT(args->at(i)->location().is_temporary()); | 578 ASSERT(args->at(i)->location().is_value()); |
| 550 } | 579 } |
| 551 // Record source position for debugger | 580 // Record source position for debugger |
| 552 SetSourcePosition(expr->position()); | 581 SetSourcePosition(expr->position()); |
| 553 // Call the IC initialization code. | 582 // Call the IC initialization code. |
| 554 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 583 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 555 NOT_IN_LOOP); | 584 NOT_IN_LOOP); |
| 556 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 585 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 557 // Restore context register. | 586 // Restore context register. |
| 558 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 587 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 559 DropAndMove(expr->location(), r0); | 588 DropAndMove(expr->location(), r0); |
| 560 } | 589 } |
| 561 | 590 |
| 562 | 591 |
| 563 void FastCodeGenerator::VisitCallNew(CallNew* node) { | 592 void FastCodeGenerator::VisitCallNew(CallNew* node) { |
| 564 Comment cmnt(masm_, "[ CallNew"); | 593 Comment cmnt(masm_, "[ CallNew"); |
| 565 // According to ECMA-262, section 11.2.2, page 44, the function | 594 // According to ECMA-262, section 11.2.2, page 44, the function |
| 566 // expression in new calls must be evaluated before the | 595 // expression in new calls must be evaluated before the |
| 567 // arguments. | 596 // arguments. |
| 568 // Push function on the stack. | 597 // Push function on the stack. |
| 569 Visit(node->expression()); | 598 Visit(node->expression()); |
| 570 ASSERT(node->expression()->location().is_temporary()); | 599 ASSERT(node->expression()->location().is_value()); |
| 571 | 600 |
| 572 // Push global object (receiver). | 601 // Push global object (receiver). |
| 573 __ ldr(r0, CodeGenerator::GlobalObject()); | 602 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 574 __ push(r0); | 603 __ push(r0); |
| 575 // Push the arguments ("left-to-right") on the stack. | 604 // Push the arguments ("left-to-right") on the stack. |
| 576 ZoneList<Expression*>* args = node->arguments(); | 605 ZoneList<Expression*>* args = node->arguments(); |
| 577 int arg_count = args->length(); | 606 int arg_count = args->length(); |
| 578 for (int i = 0; i < arg_count; i++) { | 607 for (int i = 0; i < arg_count; i++) { |
| 579 Visit(args->at(i)); | 608 Visit(args->at(i)); |
| 580 ASSERT(args->at(i)->location().is_temporary()); | 609 ASSERT(args->at(i)->location().is_value()); |
| 581 // If location is temporary, it is already on the stack, | 610 // If location is temporary, it is already on the stack, |
| 582 // so nothing to do here. | 611 // so nothing to do here. |
| 583 } | 612 } |
| 584 | 613 |
| 585 // Call the construct call builtin that handles allocation and | 614 // Call the construct call builtin that handles allocation and |
| 586 // constructor invocation. | 615 // constructor invocation. |
| 587 SetSourcePosition(node->position()); | 616 SetSourcePosition(node->position()); |
| 588 | 617 |
| 589 // Load function, arg_count into r1 and r0. | 618 // Load function, arg_count into r1 and r0. |
| 590 __ mov(r0, Operand(arg_count)); | 619 __ mov(r0, Operand(arg_count)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 603 Comment cmnt(masm_, "[ CallRuntime"); | 632 Comment cmnt(masm_, "[ CallRuntime"); |
| 604 ZoneList<Expression*>* args = expr->arguments(); | 633 ZoneList<Expression*>* args = expr->arguments(); |
| 605 Runtime::Function* function = expr->function(); | 634 Runtime::Function* function = expr->function(); |
| 606 | 635 |
| 607 ASSERT(function != NULL); | 636 ASSERT(function != NULL); |
| 608 | 637 |
| 609 // Push the arguments ("left-to-right"). | 638 // Push the arguments ("left-to-right"). |
| 610 int arg_count = args->length(); | 639 int arg_count = args->length(); |
| 611 for (int i = 0; i < arg_count; i++) { | 640 for (int i = 0; i < arg_count; i++) { |
| 612 Visit(args->at(i)); | 641 Visit(args->at(i)); |
| 613 ASSERT(args->at(i)->location().is_temporary()); | 642 ASSERT(args->at(i)->location().is_value()); |
| 614 } | 643 } |
| 615 | 644 |
| 616 __ CallRuntime(function, arg_count); | 645 __ CallRuntime(function, arg_count); |
| 617 Move(expr->location(), r0); | 646 Move(expr->location(), r0); |
| 618 } | 647 } |
| 619 | 648 |
| 620 | 649 |
| 621 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 650 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 622 // Compile a short-circuited boolean or operation in a non-test | 651 // Compile a short-circuited boolean or operation in a non-test |
| 623 // context. | 652 // context. |
| 624 ASSERT(expr->op() == Token::OR); | 653 ASSERT(expr->op() == Token::OR); |
| 625 // Compile (e0 || e1) as if it were | 654 // Compile (e0 || e1) as if it were |
| 626 // (let (temp = e0) temp ? temp : e1). | 655 // (let (temp = e0) temp ? temp : e1). |
| 627 | 656 |
| 628 Label done; | 657 Label done; |
| 629 Location destination = expr->location(); | 658 Location destination = expr->location(); |
| 630 Expression* left = expr->left(); | 659 Expression* left = expr->left(); |
| 631 Expression* right = expr->right(); | 660 Expression* right = expr->right(); |
| 632 | 661 |
| 633 // Call the runtime to find the boolean value of the left-hand | 662 // Call the runtime to find the boolean value of the left-hand |
| 634 // subexpression. Duplicate the value if it may be needed as the final | 663 // subexpression. Duplicate the value if it may be needed as the final |
| 635 // result. | 664 // result. |
| 636 if (left->AsLiteral() != NULL) { | 665 if (left->AsLiteral() != NULL) { |
| 637 __ mov(r0, Operand(left->AsLiteral()->handle())); | 666 __ mov(r0, Operand(left->AsLiteral()->handle())); |
| 638 __ push(r0); | 667 __ push(r0); |
| 639 if (destination.is_temporary()) __ push(r0); | 668 if (destination.is_value()) __ push(r0); |
| 640 } else { | 669 } else { |
| 641 Visit(left); | 670 Visit(left); |
| 642 ASSERT(left->location().is_temporary()); | 671 ASSERT(left->location().is_value()); |
| 643 if (destination.is_temporary()) { | 672 if (destination.is_value()) { |
| 644 __ ldr(r0, MemOperand(sp)); | 673 __ ldr(r0, MemOperand(sp)); |
| 645 __ push(r0); | 674 __ push(r0); |
| 646 } | 675 } |
| 647 } | 676 } |
| 648 // The left-hand value is in on top of the stack. It is duplicated on the | 677 // The left-hand value is in on top of the stack. It is duplicated on the |
| 649 // stack iff the destination location is temporary. | 678 // stack iff the destination location is temporary. |
| 650 __ CallRuntime(Runtime::kToBool, 1); | 679 __ CallRuntime(Runtime::kToBool, 1); |
| 651 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 680 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 652 __ cmp(r0, ip); | 681 __ cmp(r0, ip); |
| 653 __ b(eq, &done); | 682 __ b(eq, &done); |
| 654 | 683 |
| 655 // Discard the left-hand value if present on the stack. | 684 // Discard the left-hand value if present on the stack. |
| 656 if (destination.is_temporary()) __ pop(); | 685 if (destination.is_value()) __ pop(); |
| 657 // Save or discard the right-hand value as needed. | 686 // Save or discard the right-hand value as needed. |
| 658 if (right->AsLiteral() != NULL) { | 687 if (right->AsLiteral() != NULL) { |
| 659 Move(destination, right->AsLiteral()); | 688 Move(destination, right->AsLiteral()); |
| 660 } else { | 689 } else { |
| 661 Visit(right); | 690 Visit(right); |
| 662 Move(destination, right->location()); | 691 Move(destination, right->location()); |
| 663 } | 692 } |
| 664 | 693 |
| 665 __ bind(&done); | 694 __ bind(&done); |
| 666 } | 695 } |
| 667 | 696 |
| 668 } } // namespace v8::internal | 697 } } // namespace v8::internal |
| OLD | NEW |