| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT); | 161 const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT); |
| 162 Object* marker = Memory::Object_at(caller_fp + kMarkerOffset); | 162 Object* marker = Memory::Object_at(caller_fp + kMarkerOffset); |
| 163 bool result = (marker == kConstructMarker); | 163 bool result = (marker == kConstructMarker); |
| 164 ASSERT_EQ(result, reference_result); | 164 ASSERT_EQ(result, reference_result); |
| 165 return result; | 165 return result; |
| 166 } | 166 } |
| 167 | 167 |
| 168 // ---------------------------------------------------------------------------- | 168 // ---------------------------------------------------------------------------- |
| 169 | 169 |
| 170 | 170 |
| 171 Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) { | |
| 172 Code* code = Builtins::builtin(Builtins::Illegal); | |
| 173 *resolved = false; | |
| 174 | |
| 175 if (Top::context() != NULL) { | |
| 176 Object* object = Top::builtins()->javascript_builtin(id); | |
| 177 if (object->IsJSFunction()) { | |
| 178 Handle<SharedFunctionInfo> shared(JSFunction::cast(object)->shared()); | |
| 179 // Make sure the number of parameters match the formal parameter count. | |
| 180 ASSERT(shared->formal_parameter_count() == | |
| 181 Builtins::GetArgumentsCount(id)); | |
| 182 if (EnsureCompiled(shared, CLEAR_EXCEPTION)) { | |
| 183 code = shared->code(); | |
| 184 *resolved = true; | |
| 185 } | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 return Handle<Code>(code); | |
| 190 } | |
| 191 | |
| 192 | |
| 193 BUILTIN(Illegal) { | 171 BUILTIN(Illegal) { |
| 194 UNREACHABLE(); | 172 UNREACHABLE(); |
| 195 return Heap::undefined_value(); // Make compiler happy. | 173 return Heap::undefined_value(); // Make compiler happy. |
| 196 } | 174 } |
| 197 | 175 |
| 198 | 176 |
| 199 BUILTIN(EmptyFunction) { | 177 BUILTIN(EmptyFunction) { |
| 200 return Heap::undefined_value(); | 178 return Heap::undefined_value(); |
| 201 } | 179 } |
| 202 | 180 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 array->set_length(len); | 239 array->set_length(len); |
| 262 | 240 |
| 263 return array; | 241 return array; |
| 264 } | 242 } |
| 265 | 243 |
| 266 | 244 |
| 267 BUILTIN(ArrayPush) { | 245 BUILTIN(ArrayPush) { |
| 268 JSArray* array = JSArray::cast(*args.receiver()); | 246 JSArray* array = JSArray::cast(*args.receiver()); |
| 269 ASSERT(array->HasFastElements()); | 247 ASSERT(array->HasFastElements()); |
| 270 | 248 |
| 271 // Make sure we have space for the elements. | |
| 272 int len = Smi::cast(array->length())->value(); | 249 int len = Smi::cast(array->length())->value(); |
| 250 int to_add = args.length() - 1; |
| 251 if (to_add == 0) { |
| 252 return Smi::FromInt(len); |
| 253 } |
| 254 // Currently fixed arrays cannot grow too big, so |
| 255 // we should never hit this case. |
| 256 ASSERT(to_add <= (Smi::kMaxValue - len)); |
| 273 | 257 |
| 274 // Set new length. | 258 int new_length = len + to_add; |
| 275 int new_length = len + args.length() - 1; | |
| 276 FixedArray* elms = FixedArray::cast(array->elements()); | 259 FixedArray* elms = FixedArray::cast(array->elements()); |
| 277 | 260 |
| 278 if (new_length <= elms->length()) { | 261 if (new_length > elms->length()) { |
| 279 // Backing storage has extra space for the provided values. | |
| 280 for (int index = 0; index < args.length() - 1; index++) { | |
| 281 elms->set(index + len, args[index+1]); | |
| 282 } | |
| 283 } else { | |
| 284 // New backing storage is needed. | 262 // New backing storage is needed. |
| 285 int capacity = new_length + (new_length >> 1) + 16; | 263 int capacity = new_length + (new_length >> 1) + 16; |
| 286 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); | 264 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
| 287 if (obj->IsFailure()) return obj; | 265 if (obj->IsFailure()) return obj; |
| 288 | 266 |
| 289 AssertNoAllocation no_gc; | 267 AssertNoAllocation no_gc; |
| 290 FixedArray* new_elms = FixedArray::cast(obj); | 268 FixedArray* new_elms = FixedArray::cast(obj); |
| 291 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); | 269 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); |
| 292 // Fill out the new array with old elements. | 270 // Fill out the new array with old elements. |
| 293 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode); | 271 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode); |
| 294 // Add the provided values. | 272 elms = new_elms; |
| 295 for (int index = 0; index < args.length() - 1; index++) { | 273 array->set_elements(elms); |
| 296 new_elms->set(index + len, args[index+1], mode); | |
| 297 } | |
| 298 // Set the new backing storage. | |
| 299 array->set_elements(new_elms); | |
| 300 } | 274 } |
| 275 |
| 276 AssertNoAllocation no_gc; |
| 277 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 278 |
| 279 // Add the provided values. |
| 280 for (int index = 0; index < to_add; index++) { |
| 281 elms->set(index + len, args[index + 1], mode); |
| 282 } |
| 283 |
| 301 // Set the length. | 284 // Set the length. |
| 302 array->set_length(Smi::FromInt(new_length)); | 285 array->set_length(Smi::FromInt(new_length)); |
| 303 return array->length(); | 286 return Smi::FromInt(new_length); |
| 304 } | 287 } |
| 305 | 288 |
| 306 | 289 |
| 307 BUILTIN(ArrayPop) { | 290 BUILTIN(ArrayPop) { |
| 308 JSArray* array = JSArray::cast(*args.receiver()); | 291 JSArray* array = JSArray::cast(*args.receiver()); |
| 309 ASSERT(array->HasFastElements()); | 292 ASSERT(array->HasFastElements()); |
| 310 Object* undefined = Heap::undefined_value(); | 293 Object* undefined = Heap::undefined_value(); |
| 311 | 294 |
| 312 int len = Smi::cast(array->length())->value(); | 295 int len = Smi::cast(array->length())->value(); |
| 313 if (len == 0) return undefined; | 296 if (len == 0) return undefined; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 328 // Remember to check the prototype chain. | 311 // Remember to check the prototype chain. |
| 329 JSFunction* array_function = | 312 JSFunction* array_function = |
| 330 Top::context()->global_context()->array_function(); | 313 Top::context()->global_context()->array_function(); |
| 331 JSObject* prototype = JSObject::cast(array_function->prototype()); | 314 JSObject* prototype = JSObject::cast(array_function->prototype()); |
| 332 top = prototype->GetElement(len - 1); | 315 top = prototype->GetElement(len - 1); |
| 333 | 316 |
| 334 return top; | 317 return top; |
| 335 } | 318 } |
| 336 | 319 |
| 337 | 320 |
| 321 static Object* GetElementToMove(uint32_t index, |
| 322 FixedArray* elms, |
| 323 JSObject* prototype) { |
| 324 Object* e = elms->get(index); |
| 325 if (e->IsTheHole() && prototype->HasElement(index)) { |
| 326 e = prototype->GetElement(index); |
| 327 } |
| 328 return e; |
| 329 } |
| 330 |
| 331 |
| 332 BUILTIN(ArrayShift) { |
| 333 JSArray* array = JSArray::cast(*args.receiver()); |
| 334 ASSERT(array->HasFastElements()); |
| 335 |
| 336 int len = Smi::cast(array->length())->value(); |
| 337 if (len == 0) return Heap::undefined_value(); |
| 338 |
| 339 // Fetch the prototype. |
| 340 JSFunction* array_function = |
| 341 Top::context()->global_context()->array_function(); |
| 342 JSObject* prototype = JSObject::cast(array_function->prototype()); |
| 343 |
| 344 FixedArray* elms = FixedArray::cast(array->elements()); |
| 345 |
| 346 // Get first element |
| 347 Object* first = elms->get(0); |
| 348 if (first->IsTheHole()) { |
| 349 first = prototype->GetElement(0); |
| 350 } |
| 351 |
| 352 // Shift the elements. |
| 353 for (int i = 0; i < len - 1; i++) { |
| 354 elms->set(i, GetElementToMove(i + 1, elms, prototype)); |
| 355 } |
| 356 elms->set(len - 1, Heap::the_hole_value()); |
| 357 |
| 358 // Set the length. |
| 359 array->set_length(Smi::FromInt(len - 1)); |
| 360 |
| 361 return first; |
| 362 } |
| 363 |
| 364 |
| 365 BUILTIN(ArrayUnshift) { |
| 366 JSArray* array = JSArray::cast(*args.receiver()); |
| 367 ASSERT(array->HasFastElements()); |
| 368 |
| 369 int len = Smi::cast(array->length())->value(); |
| 370 int to_add = args.length() - 1; |
| 371 // Note that we cannot quit early if to_add == 0 as |
| 372 // values should be lifted from prototype into |
| 373 // the array. |
| 374 |
| 375 int new_length = len + to_add; |
| 376 // Currently fixed arrays cannot grow too big, so |
| 377 // we should never hit this case. |
| 378 ASSERT(to_add <= (Smi::kMaxValue - len)); |
| 379 |
| 380 FixedArray* elms = FixedArray::cast(array->elements()); |
| 381 |
| 382 // Fetch the prototype. |
| 383 JSFunction* array_function = |
| 384 Top::context()->global_context()->array_function(); |
| 385 JSObject* prototype = JSObject::cast(array_function->prototype()); |
| 386 |
| 387 if (new_length > elms->length()) { |
| 388 // New backing storage is needed. |
| 389 int capacity = new_length + (new_length >> 1) + 16; |
| 390 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
| 391 if (obj->IsFailure()) return obj; |
| 392 |
| 393 AssertNoAllocation no_gc; |
| 394 FixedArray* new_elms = FixedArray::cast(obj); |
| 395 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); |
| 396 // Fill out the new array with old elements. |
| 397 for (int i = 0; i < len; i++) |
| 398 new_elms->set(to_add + i, |
| 399 GetElementToMove(i, elms, prototype), |
| 400 mode); |
| 401 |
| 402 elms = new_elms; |
| 403 array->set_elements(elms); |
| 404 } else { |
| 405 AssertNoAllocation no_gc; |
| 406 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 407 |
| 408 // Move elements to the right |
| 409 for (int i = 0; i < len; i++) { |
| 410 elms->set(new_length - i - 1, |
| 411 GetElementToMove(len - i - 1, elms, prototype), |
| 412 mode); |
| 413 } |
| 414 } |
| 415 |
| 416 // Add the provided values. |
| 417 AssertNoAllocation no_gc; |
| 418 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 419 for (int i = 0; i < to_add; i++) { |
| 420 elms->set(i, args[i + 1], mode); |
| 421 } |
| 422 |
| 423 // Set the length. |
| 424 array->set_length(Smi::FromInt(new_length)); |
| 425 return Smi::FromInt(new_length); |
| 426 } |
| 427 |
| 428 |
| 429 static Object* CallJsBuiltin(const char* name, |
| 430 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
| 431 HandleScope handleScope; |
| 432 |
| 433 Handle<Object> js_builtin = |
| 434 GetProperty(Handle<JSObject>(Top::global_context()->builtins()), |
| 435 name); |
| 436 ASSERT(js_builtin->IsJSFunction()); |
| 437 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin)); |
| 438 Vector<Object**> argv(Vector<Object**>::New(args.length() - 1)); |
| 439 int n_args = args.length() - 1; |
| 440 for (int i = 0; i < n_args; i++) { |
| 441 argv[i] = &args[i + 1]; |
| 442 } |
| 443 bool pending_exception = false; |
| 444 Handle<Object> result = Execution::Call(function, |
| 445 args.receiver(), |
| 446 n_args, |
| 447 argv.start(), |
| 448 &pending_exception); |
| 449 if (pending_exception) return Failure::Exception(); |
| 450 return *result; |
| 451 } |
| 452 |
| 453 |
| 454 BUILTIN(ArraySlice) { |
| 455 JSArray* array = JSArray::cast(*args.receiver()); |
| 456 ASSERT(array->HasFastElements()); |
| 457 |
| 458 int len = Smi::cast(array->length())->value(); |
| 459 |
| 460 int n_arguments = args.length() - 1; |
| 461 |
| 462 // Note carefully choosen defaults---if argument is missing, |
| 463 // it's undefined which gets converted to 0 for relativeStart |
| 464 // and to len for relativeEnd. |
| 465 int relativeStart = 0; |
| 466 int relativeEnd = len; |
| 467 if (n_arguments > 0) { |
| 468 Object* arg1 = args[1]; |
| 469 if (arg1->IsSmi()) { |
| 470 relativeStart = Smi::cast(arg1)->value(); |
| 471 } else if (!arg1->IsUndefined()) { |
| 472 return CallJsBuiltin("ArraySlice", args); |
| 473 } |
| 474 if (n_arguments > 1) { |
| 475 Object* arg2 = args[2]; |
| 476 if (arg2->IsSmi()) { |
| 477 relativeEnd = Smi::cast(arg2)->value(); |
| 478 } else if (!arg2->IsUndefined()) { |
| 479 return CallJsBuiltin("ArraySlice", args); |
| 480 } |
| 481 } |
| 482 } |
| 483 |
| 484 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. |
| 485 int k = (relativeStart < 0) ? Max(len + relativeStart, 0) |
| 486 : Min(relativeStart, len); |
| 487 |
| 488 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. |
| 489 int final = (relativeEnd < 0) ? Max(len + relativeEnd, 0) |
| 490 : Min(relativeEnd, len); |
| 491 |
| 492 // Calculate the length of result array. |
| 493 int result_len = final - k; |
| 494 if (result_len < 0) { |
| 495 result_len = 0; |
| 496 } |
| 497 |
| 498 JSFunction* array_function = |
| 499 Top::context()->global_context()->array_function(); |
| 500 Object* result = Heap::AllocateJSObject(array_function); |
| 501 if (result->IsFailure()) return result; |
| 502 JSArray* result_array = JSArray::cast(result); |
| 503 |
| 504 result = Heap::AllocateFixedArrayWithHoles(result_len); |
| 505 if (result->IsFailure()) return result; |
| 506 FixedArray* result_elms = FixedArray::cast(result); |
| 507 |
| 508 FixedArray* elms = FixedArray::cast(array->elements()); |
| 509 |
| 510 // Fetch the prototype. |
| 511 JSObject* prototype = JSObject::cast(array_function->prototype()); |
| 512 |
| 513 AssertNoAllocation no_gc; |
| 514 WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc); |
| 515 |
| 516 // Fill newly created array. |
| 517 for (int i = 0; i < result_len; i++) { |
| 518 result_elms->set(i, |
| 519 GetElementToMove(k + i, elms, prototype), |
| 520 mode); |
| 521 } |
| 522 |
| 523 // Set elements. |
| 524 result_array->set_elements(result_elms); |
| 525 |
| 526 // Set the length. |
| 527 result_array->set_length(Smi::FromInt(result_len)); |
| 528 return result_array; |
| 529 } |
| 530 |
| 531 |
| 532 BUILTIN(ArraySplice) { |
| 533 JSArray* array = JSArray::cast(*args.receiver()); |
| 534 ASSERT(array->HasFastElements()); |
| 535 |
| 536 int len = Smi::cast(array->length())->value(); |
| 537 |
| 538 int n_arguments = args.length() - 1; |
| 539 |
| 540 // SpiderMonkey and JSC return undefined in the case where no |
| 541 // arguments are given instead of using the implicit undefined |
| 542 // arguments. This does not follow ECMA-262, but we do the same for |
| 543 // compatibility. |
| 544 // TraceMonkey follows ECMA-262 though. |
| 545 if (n_arguments == 0) { |
| 546 return Heap::undefined_value(); |
| 547 } |
| 548 |
| 549 int relativeStart = 0; |
| 550 Object* arg1 = args[1]; |
| 551 if (arg1->IsSmi()) { |
| 552 relativeStart = Smi::cast(arg1)->value(); |
| 553 } else if (!arg1->IsUndefined()) { |
| 554 return CallJsBuiltin("ArraySplice", args); |
| 555 } |
| 556 int actualStart = (relativeStart < 0) ? Max(len + relativeStart, 0) |
| 557 : Min(relativeStart, len); |
| 558 |
| 559 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is |
| 560 // given differently from when an undefined delete count is given. |
| 561 // This does not follow ECMA-262, but we do the same for |
| 562 // compatibility. |
| 563 int deleteCount = len; |
| 564 if (n_arguments > 1) { |
| 565 Object* arg2 = args[2]; |
| 566 if (arg2->IsSmi()) { |
| 567 deleteCount = Smi::cast(arg2)->value(); |
| 568 } else { |
| 569 return CallJsBuiltin("ArraySplice", args); |
| 570 } |
| 571 } |
| 572 int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart); |
| 573 |
| 574 JSFunction* array_function = |
| 575 Top::context()->global_context()->array_function(); |
| 576 |
| 577 // Allocate result array. |
| 578 Object* result = Heap::AllocateJSObject(array_function); |
| 579 if (result->IsFailure()) return result; |
| 580 JSArray* result_array = JSArray::cast(result); |
| 581 |
| 582 result = Heap::AllocateFixedArrayWithHoles(actualDeleteCount); |
| 583 if (result->IsFailure()) return result; |
| 584 FixedArray* result_elms = FixedArray::cast(result); |
| 585 |
| 586 FixedArray* elms = FixedArray::cast(array->elements()); |
| 587 |
| 588 // Fetch the prototype. |
| 589 JSObject* prototype = JSObject::cast(array_function->prototype()); |
| 590 |
| 591 AssertNoAllocation no_gc; |
| 592 WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc); |
| 593 |
| 594 // Fill newly created array. |
| 595 for (int k = 0; k < actualDeleteCount; k++) { |
| 596 result_elms->set(k, |
| 597 GetElementToMove(actualStart + k, elms, prototype), |
| 598 mode); |
| 599 } |
| 600 |
| 601 // Set elements. |
| 602 result_array->set_elements(result_elms); |
| 603 |
| 604 // Set the length. |
| 605 result_array->set_length(Smi::FromInt(actualDeleteCount)); |
| 606 |
| 607 int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0; |
| 608 |
| 609 int new_length = len - actualDeleteCount + itemCount; |
| 610 |
| 611 mode = elms->GetWriteBarrierMode(no_gc); |
| 612 if (itemCount < actualDeleteCount) { |
| 613 // Shrink the array. |
| 614 for (int k = actualStart; k < (len - actualDeleteCount); k++) { |
| 615 elms->set(k + itemCount, |
| 616 GetElementToMove(k + actualDeleteCount, elms, prototype), |
| 617 mode); |
| 618 } |
| 619 |
| 620 for (int k = len; k > new_length; k--) { |
| 621 elms->set(k - 1, Heap::the_hole_value()); |
| 622 } |
| 623 } else if (itemCount > actualDeleteCount) { |
| 624 // Currently fixed arrays cannot grow too big, so |
| 625 // we should never hit this case. |
| 626 ASSERT((itemCount - actualDeleteCount) <= (Smi::kMaxValue - len)); |
| 627 |
| 628 FixedArray* source_elms = elms; |
| 629 |
| 630 // Check if array need to grow. |
| 631 if (new_length > elms->length()) { |
| 632 // New backing storage is needed. |
| 633 int capacity = new_length + (new_length >> 1) + 16; |
| 634 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
| 635 if (obj->IsFailure()) return obj; |
| 636 |
| 637 FixedArray* new_elms = FixedArray::cast(obj); |
| 638 mode = new_elms->GetWriteBarrierMode(no_gc); |
| 639 |
| 640 // Copy the part before actualStart as is. |
| 641 for (int k = 0; k < actualStart; k++) { |
| 642 new_elms->set(k, elms->get(k), mode); |
| 643 } |
| 644 |
| 645 source_elms = elms; |
| 646 elms = new_elms; |
| 647 array->set_elements(elms); |
| 648 } |
| 649 |
| 650 for (int k = len - actualDeleteCount; k > actualStart; k--) { |
| 651 elms->set(k + itemCount - 1, |
| 652 GetElementToMove(k + actualDeleteCount - 1, |
| 653 source_elms, |
| 654 prototype), |
| 655 mode); |
| 656 } |
| 657 } |
| 658 |
| 659 for (int k = actualStart; k < actualStart + itemCount; k++) { |
| 660 elms->set(k, args[3 + k - actualStart], mode); |
| 661 } |
| 662 |
| 663 // Set the length. |
| 664 array->set_length(Smi::FromInt(new_length)); |
| 665 |
| 666 return result_array; |
| 667 } |
| 668 |
| 669 |
| 338 // ----------------------------------------------------------------------------- | 670 // ----------------------------------------------------------------------------- |
| 339 // | 671 // |
| 340 | 672 |
| 341 | 673 |
| 342 // Returns the holder JSObject if the function can legally be called | 674 // Returns the holder JSObject if the function can legally be called |
| 343 // with this receiver. Returns Heap::null_value() if the call is | 675 // with this receiver. Returns Heap::null_value() if the call is |
| 344 // illegal. Any arguments that don't fit the expected type is | 676 // illegal. Any arguments that don't fit the expected type is |
| 345 // overwritten with undefined. Arguments that do fit the expected | 677 // overwritten with undefined. Arguments that do fit the expected |
| 346 // type is overwritten with the object in the prototype chain that | 678 // type is overwritten with the object in the prototype chain that |
| 347 // actually has that type. | 679 // actually has that type. |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 BUILTIN(HandleApiCall) { | 799 BUILTIN(HandleApiCall) { |
| 468 return HandleApiCallHelper<false>(args); | 800 return HandleApiCallHelper<false>(args); |
| 469 } | 801 } |
| 470 | 802 |
| 471 | 803 |
| 472 BUILTIN(HandleApiCallConstruct) { | 804 BUILTIN(HandleApiCallConstruct) { |
| 473 return HandleApiCallHelper<true>(args); | 805 return HandleApiCallHelper<true>(args); |
| 474 } | 806 } |
| 475 | 807 |
| 476 | 808 |
| 809 #ifdef DEBUG |
| 810 |
| 811 static void VerifyTypeCheck(Handle<JSObject> object, |
| 812 Handle<JSFunction> function) { |
| 813 FunctionTemplateInfo* info = |
| 814 FunctionTemplateInfo::cast(function->shared()->function_data()); |
| 815 if (info->signature()->IsUndefined()) return; |
| 816 SignatureInfo* signature = SignatureInfo::cast(info->signature()); |
| 817 Object* receiver_type = signature->receiver(); |
| 818 if (receiver_type->IsUndefined()) return; |
| 819 FunctionTemplateInfo* type = FunctionTemplateInfo::cast(receiver_type); |
| 820 ASSERT(object->IsInstanceOf(type)); |
| 821 } |
| 822 |
| 823 #endif |
| 824 |
| 825 |
| 826 BUILTIN(FastHandleApiCall) { |
| 827 ASSERT(!CalledAsConstructor()); |
| 828 const bool is_construct = false; |
| 829 |
| 830 // We expect four more arguments: function, callback, call data, and holder. |
| 831 const int args_length = args.length() - 4; |
| 832 ASSERT(args_length >= 0); |
| 833 |
| 834 Handle<JSFunction> function = args.at<JSFunction>(args_length); |
| 835 Object* callback_obj = args[args_length + 1]; |
| 836 Handle<Object> data_handle = args.at<Object>(args_length + 2); |
| 837 Handle<JSObject> checked_holder = args.at<JSObject>(args_length + 3); |
| 838 |
| 839 #ifdef DEBUG |
| 840 VerifyTypeCheck(checked_holder, function); |
| 841 #endif |
| 842 |
| 843 v8::Local<v8::Object> holder = v8::Utils::ToLocal(checked_holder); |
| 844 v8::Local<v8::Function> callee = v8::Utils::ToLocal(function); |
| 845 v8::InvocationCallback callback = |
| 846 v8::ToCData<v8::InvocationCallback>(callback_obj); |
| 847 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle); |
| 848 |
| 849 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( |
| 850 data, |
| 851 holder, |
| 852 callee, |
| 853 is_construct, |
| 854 reinterpret_cast<void**>(&args[0] - 1), |
| 855 args_length - 1); |
| 856 |
| 857 HandleScope scope; |
| 858 Object* result; |
| 859 v8::Handle<v8::Value> value; |
| 860 { |
| 861 // Leaving JavaScript. |
| 862 VMState state(EXTERNAL); |
| 863 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 864 state.set_external_callback(v8::ToCData<Address>(callback_obj)); |
| 865 #endif |
| 866 value = callback(new_args); |
| 867 } |
| 868 if (value.IsEmpty()) { |
| 869 result = Heap::undefined_value(); |
| 870 } else { |
| 871 result = *reinterpret_cast<Object**>(*value); |
| 872 } |
| 873 |
| 874 RETURN_IF_SCHEDULED_EXCEPTION(); |
| 875 return result; |
| 876 } |
| 877 |
| 878 |
| 477 // Helper function to handle calls to non-function objects created through the | 879 // Helper function to handle calls to non-function objects created through the |
| 478 // API. The object can be called as either a constructor (using new) or just as | 880 // API. The object can be called as either a constructor (using new) or just as |
| 479 // a function (without new). | 881 // a function (without new). |
| 480 static Object* HandleApiCallAsFunctionOrConstructor( | 882 static Object* HandleApiCallAsFunctionOrConstructor( |
| 481 bool is_construct_call, | 883 bool is_construct_call, |
| 482 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { | 884 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
| 483 // Non-functions are never called as constructors. Even if this is an object | 885 // Non-functions are never called as constructors. Even if this is an object |
| 484 // called as a constructor the delegate call is not a construct call. | 886 // called as a constructor the delegate call is not a construct call. |
| 485 ASSERT(!CalledAsConstructor()); | 887 ASSERT(!CalledAsConstructor()); |
| 486 | 888 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 | 1052 |
| 651 static void Generate_KeyedLoadIC_ExternalFloatArray(MacroAssembler* masm) { | 1053 static void Generate_KeyedLoadIC_ExternalFloatArray(MacroAssembler* masm) { |
| 652 KeyedLoadIC::GenerateExternalArray(masm, kExternalFloatArray); | 1054 KeyedLoadIC::GenerateExternalArray(masm, kExternalFloatArray); |
| 653 } | 1055 } |
| 654 | 1056 |
| 655 | 1057 |
| 656 static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) { | 1058 static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) { |
| 657 KeyedLoadIC::GeneratePreMonomorphic(masm); | 1059 KeyedLoadIC::GeneratePreMonomorphic(masm); |
| 658 } | 1060 } |
| 659 | 1061 |
| 1062 static void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) { |
| 1063 KeyedLoadIC::GenerateIndexedInterceptor(masm); |
| 1064 } |
| 1065 |
| 660 | 1066 |
| 661 static void Generate_StoreIC_Initialize(MacroAssembler* masm) { | 1067 static void Generate_StoreIC_Initialize(MacroAssembler* masm) { |
| 662 StoreIC::GenerateInitialize(masm); | 1068 StoreIC::GenerateInitialize(masm); |
| 663 } | 1069 } |
| 664 | 1070 |
| 665 | 1071 |
| 666 static void Generate_StoreIC_Miss(MacroAssembler* masm) { | 1072 static void Generate_StoreIC_Miss(MacroAssembler* masm) { |
| 667 StoreIC::GenerateMiss(masm); | 1073 StoreIC::GenerateMiss(masm); |
| 668 } | 1074 } |
| 669 | 1075 |
| 670 | 1076 |
| 671 static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) { | |
| 672 StoreIC::GenerateExtendStorage(masm); | |
| 673 } | |
| 674 | |
| 675 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) { | 1077 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) { |
| 676 StoreIC::GenerateMegamorphic(masm); | 1078 StoreIC::GenerateMegamorphic(masm); |
| 677 } | 1079 } |
| 678 | 1080 |
| 679 | 1081 |
| 1082 static void Generate_StoreIC_ArrayLength(MacroAssembler* masm) { |
| 1083 StoreIC::GenerateArrayLength(masm); |
| 1084 } |
| 1085 |
| 1086 |
| 680 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) { | 1087 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) { |
| 681 KeyedStoreIC::GenerateGeneric(masm); | 1088 KeyedStoreIC::GenerateGeneric(masm); |
| 682 } | 1089 } |
| 683 | 1090 |
| 684 | 1091 |
| 685 static void Generate_KeyedStoreIC_ExternalByteArray(MacroAssembler* masm) { | 1092 static void Generate_KeyedStoreIC_ExternalByteArray(MacroAssembler* masm) { |
| 686 KeyedStoreIC::GenerateExternalArray(masm, kExternalByteArray); | 1093 KeyedStoreIC::GenerateExternalArray(masm, kExternalByteArray); |
| 687 } | 1094 } |
| 688 | 1095 |
| 689 | 1096 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 713 MacroAssembler* masm) { | 1120 MacroAssembler* masm) { |
| 714 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedIntArray); | 1121 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedIntArray); |
| 715 } | 1122 } |
| 716 | 1123 |
| 717 | 1124 |
| 718 static void Generate_KeyedStoreIC_ExternalFloatArray(MacroAssembler* masm) { | 1125 static void Generate_KeyedStoreIC_ExternalFloatArray(MacroAssembler* masm) { |
| 719 KeyedStoreIC::GenerateExternalArray(masm, kExternalFloatArray); | 1126 KeyedStoreIC::GenerateExternalArray(masm, kExternalFloatArray); |
| 720 } | 1127 } |
| 721 | 1128 |
| 722 | 1129 |
| 723 static void Generate_KeyedStoreIC_ExtendStorage(MacroAssembler* masm) { | |
| 724 KeyedStoreIC::GenerateExtendStorage(masm); | |
| 725 } | |
| 726 | |
| 727 | |
| 728 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) { | 1130 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) { |
| 729 KeyedStoreIC::GenerateMiss(masm); | 1131 KeyedStoreIC::GenerateMiss(masm); |
| 730 } | 1132 } |
| 731 | 1133 |
| 732 | 1134 |
| 733 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) { | 1135 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) { |
| 734 KeyedStoreIC::GenerateInitialize(masm); | 1136 KeyedStoreIC::GenerateInitialize(masm); |
| 735 } | 1137 } |
| 736 | 1138 |
| 737 | 1139 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 Object* code; | 1264 Object* code; |
| 863 { | 1265 { |
| 864 // During startup it's OK to always allocate and defer GC to later. | 1266 // During startup it's OK to always allocate and defer GC to later. |
| 865 // This simplifies things because we don't need to retry. | 1267 // This simplifies things because we don't need to retry. |
| 866 AlwaysAllocateScope __scope__; | 1268 AlwaysAllocateScope __scope__; |
| 867 code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject()); | 1269 code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject()); |
| 868 if (code->IsFailure()) { | 1270 if (code->IsFailure()) { |
| 869 v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); | 1271 v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); |
| 870 } | 1272 } |
| 871 } | 1273 } |
| 872 // Add any unresolved jumps or calls to the fixup list in the | |
| 873 // bootstrapper. | |
| 874 Bootstrapper::AddFixup(Code::cast(code), &masm); | |
| 875 // Log the event and add the code to the builtins array. | 1274 // Log the event and add the code to the builtins array. |
| 876 LOG(CodeCreateEvent(Logger::BUILTIN_TAG, | 1275 LOG(CodeCreateEvent(Logger::BUILTIN_TAG, |
| 877 Code::cast(code), functions[i].s_name)); | 1276 Code::cast(code), functions[i].s_name)); |
| 878 builtins_[i] = code; | 1277 builtins_[i] = code; |
| 879 #ifdef ENABLE_DISASSEMBLER | 1278 #ifdef ENABLE_DISASSEMBLER |
| 880 if (FLAG_print_builtin_code) { | 1279 if (FLAG_print_builtin_code) { |
| 881 PrintF("Builtin: %s\n", functions[i].s_name); | 1280 PrintF("Builtin: %s\n", functions[i].s_name); |
| 882 Code::cast(code)->Disassemble(functions[i].s_name); | 1281 Code::cast(code)->Disassemble(functions[i].s_name); |
| 883 PrintF("\n"); | 1282 PrintF("\n"); |
| 884 } | 1283 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 912 if (entry->contains(pc)) { | 1311 if (entry->contains(pc)) { |
| 913 return names_[i]; | 1312 return names_[i]; |
| 914 } | 1313 } |
| 915 } | 1314 } |
| 916 } | 1315 } |
| 917 return NULL; | 1316 return NULL; |
| 918 } | 1317 } |
| 919 | 1318 |
| 920 | 1319 |
| 921 } } // namespace v8::internal | 1320 } } // namespace v8::internal |
| OLD | NEW |