blob: 374f2801a67d434fa3c9af67deba17c4c9bcfb5a [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001// Copyright 2006-2008 Google Inc. All Rights Reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
30#include "v8.h"
31
32#include "accessors.h"
33#include "api.h"
34#include "arguments.h"
35#include "compiler.h"
36#include "cpu.h"
37#include "dateparser.h"
38#include "debug.h"
39#include "execution.h"
40#include "jsregexp.h"
41#include "platform.h"
42#include "runtime.h"
43#include "scopeinfo.h"
44#include "v8threads.h"
45
46namespace v8 { namespace internal {
47
48
49#define RUNTIME_ASSERT(value) do { \
50 if (!(value)) return IllegalOperation(); \
51} while (false)
52
53// Cast the given object to a value of the specified type and store
54// it in a variable with the given name. If the object is not of the
55// expected type call IllegalOperation and return.
56#define CONVERT_CHECKED(Type, name, obj) \
57 RUNTIME_ASSERT(obj->Is##Type()); \
58 Type* name = Type::cast(obj);
59
60#define CONVERT_ARG_CHECKED(Type, name, index) \
61 RUNTIME_ASSERT(args[index]->Is##Type()); \
62 Handle<Type> name = args.at<Type>(index);
63
64// Cast the given object to a double and store it in a variable with
65// the given name. If the object is not a number (as opposed to
66// the number not-a-number) call IllegalOperation and return.
67#define CONVERT_DOUBLE_CHECKED(name, obj) \
68 RUNTIME_ASSERT(obj->IsNumber()); \
69 double name = (obj)->Number();
70
71// Call the specified converter on the object *comand store the result in
72// a variable of the specified type with the given name. If the
73// object is not a Number call IllegalOperation and return.
74#define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
75 RUNTIME_ASSERT(obj->IsNumber()); \
76 type name = NumberTo##Type(obj);
77
78// Non-reentrant string buffer for efficient general use in this file.
79static StaticResource<StringInputBuffer> string_input_buffer;
80
81
82static Object* IllegalOperation() {
83 return Top::Throw(Heap::illegal_access_symbol());
84}
85
86
87static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) {
88 CONVERT_CHECKED(JSObject, boilerplate, args[0]);
89
90#ifdef DEBUG
91 // Verify the constructor of the boilerplate is equal to the
92 // object function in the CURRENT global_context.
93 CHECK(boilerplate->map()->constructor()
94 == Top::context()->global_context()->object_function());
95#endif
96 return boilerplate->Copy();
97}
98
99
100static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
101 HandleScope scope;
102 ASSERT(args.length() == 3);
103 // Copy the arguments.
104 Handle<FixedArray> literals = args.at<FixedArray>(0);
105 int literals_index = Smi::cast(args[1])->value();
106 Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
107
108 // Create the boilerplate object for the function literal
109 Handle<JSObject> boilerplate =
110 Factory::NewJSObject(Top::object_function(), TENURED);
111
112 { // Add the constant propeties to the boilerplate.
113 int length = constant_properties->length();
114 OptimizedObjectForAddingMultipleProperties opt(boilerplate, true);
115 for (int index = 0; index < length; index +=2) {
116 Handle<Object> key(constant_properties->get(index+0));
117 Handle<Object> value(constant_properties->get(index+1));
118 uint32_t element_index = 0;
119 if (key->IsSymbol()) {
120 // If key is a symbol it is not an array element.
121 Handle<String> name(String::cast(*key));
122 ASSERT(!name->AsArrayIndex(&element_index));
123 SetProperty(boilerplate, name, value, NONE);
124 } else if (Array::IndexFromObject(*key, &element_index)) {
125 // Array index (uint32).
126 SetElement(boilerplate, element_index, value);
127 } else {
128 // Non-uint32 number.
129 ASSERT(key->IsNumber());
130 double num = key->Number();
131 char arr[100];
132 Vector<char> buffer(arr, ARRAY_SIZE(arr));
133 const char* str = DoubleToCString(num, buffer);
134 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
135 SetProperty(boilerplate, name, value, NONE);
136 }
137 }
138 }
139
140 // Update the functions literal and return the boilerplate.
141 literals->set(literals_index, *boilerplate);
142
143 return *boilerplate;
144}
145
146
147static Object* Runtime_CreateArrayLiteral(Arguments args) {
148 // Takes a FixedArray containing literals and produces
149 // JSArray with the elements matching the literals.
150 ASSERT(args.length() == 1);
151 CONVERT_CHECKED(FixedArray, literals, args[0]);
152
153 // Retrieve the array constructor from the global context.
154 JSFunction* constructor =
155 JSFunction::cast(Top::context()->global_context()->array_function());
156
157 // Create the JSArray.
158 Object* object = Heap::AllocateJSObject(constructor);
159 if (object->IsFailure()) return object;
160
161 // Copy the literals.
162 Object* elements = literals->Copy();
163 if (elements->IsFailure()) return elements;
164
165 // Set the elements.
166 JSArray::cast(object)->SetContent(FixedArray::cast(elements));
167 return object;
168}
169
170
171static Object* Runtime_ClassOf(Arguments args) {
172 NoHandleAllocation ha;
173 ASSERT(args.length() == 1);
174 Object* obj = args[0];
175 if (!obj->IsJSObject()) return Heap::null_value();
176 return JSObject::cast(obj)->class_name();
177}
178
179
180static Object* Runtime_IsInPrototypeChain(Arguments args) {
181 NoHandleAllocation ha;
182 ASSERT(args.length() == 2);
183 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
184 Object* O = args[0];
185 Object* V = args[1];
186 while (true) {
187 Object* prototype = V->GetPrototype();
188 if (prototype->IsNull()) return Heap::false_value();
189 if (O == prototype) return Heap::true_value();
190 V = prototype;
191 }
192}
193
194
195static Object* Runtime_IsConstructCall(Arguments args) {
196 NoHandleAllocation ha;
197 JavaScriptFrameIterator it;
198 return Heap::ToBoolean(it.frame()->IsConstructor());
199}
200
201
202static Object* Runtime_GetBuiltins(Arguments args) {
203 NoHandleAllocation ha;
204 return Top::context()->builtins();
205}
206
207
208static Object* Runtime_RegExpCompile(Arguments args) {
209 HandleScope scope; // create a new handle scope
210 ASSERT(args.length() == 3);
211 CONVERT_CHECKED(JSValue, raw_re, args[0]);
212 Handle<JSValue> re(raw_re);
213 CONVERT_CHECKED(String, raw_pattern, args[1]);
214 Handle<String> pattern(raw_pattern);
215 CONVERT_CHECKED(String, raw_flags, args[2]);
216 Handle<String> flags(raw_flags);
217 return *RegExpImpl::JsreCompile(re, pattern, flags);
218}
219
220
221static Object* Runtime_CreateApiFunction(Arguments args) {
222 HandleScope scope;
223 ASSERT(args.length() == 1);
224 CONVERT_CHECKED(FunctionTemplateInfo, raw_data, args[0]);
225 Handle<FunctionTemplateInfo> data(raw_data);
226 return *Factory::CreateApiFunction(data);
227}
228
229
230static Object* Runtime_IsTemplate(Arguments args) {
231 ASSERT(args.length() == 1);
232 Object* arg = args[0];
233 bool result = arg->IsObjectTemplateInfo()
234 || arg->IsFunctionTemplateInfo();
235 return Heap::ToBoolean(result);
236}
237
238
239static Object* Runtime_GetTemplateField(Arguments args) {
240 ASSERT(args.length() == 2);
241 CONVERT_CHECKED(HeapObject, templ, args[0]);
242 RUNTIME_ASSERT(templ->IsStruct());
243 CONVERT_CHECKED(Smi, field, args[1]);
244 return HeapObject::GetHeapObjectField(templ, field->value());
245}
246
247
248static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {
249 HandleScope scope;
250 Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
251 Handle<Object> args[2] = { type_handle, name };
252 Handle<Object> error =
253 Factory::NewTypeError("redeclaration", HandleVector(args, 2));
254 return Top::Throw(*error);
255}
256
257
258static Object* Runtime_DeclareGlobals(Arguments args) {
259 HandleScope scope;
260 Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
261
262 CONVERT_ARG_CHECKED(FixedArray, pairs, 0);
263 Handle<Context> context = args.at<Context>(1);
264 bool is_eval = Smi::cast(args[2])->value() == 1;
265
266 // Compute the property attributes. According to ECMA-262, section
267 // 13, page 71, the property must be read-only and
268 // non-deletable. However, neither SpiderMonkey nor KJS creates the
269 // property as read-only, so we don't either.
270 PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
271
272 // Only optimize the object if we intend to add more than 5 properties.
273 OptimizedObjectForAddingMultipleProperties ba(global, pairs->length()/2 > 5);
274
275 // Traverse the name/value pairs and set the properties.
276 int length = pairs->length();
277 for (int i = 0; i < length; i += 2) {
278 HandleScope scope;
279 Handle<String> name(String::cast(pairs->get(i)));
280 Handle<Object> value(pairs->get(i + 1));
281
282 // We have to declare a global const property. To capture we only
283 // assign to it when evaluating the assignment for "const x =
284 // <expr>" the initial value is the hole.
285 bool is_const_property = value->IsTheHole();
286
287 if (value->IsUndefined() || is_const_property) {
288 // Lookup the property in the global object, and don't set the
289 // value of the variable if the property is already there.
290 LookupResult lookup;
291 global->Lookup(*name, &lookup);
292 if (lookup.IsProperty()) {
293 // Determine if the property is local by comparing the holder
294 // against the global object. The information will be used to
295 // avoid throwing re-declaration errors when declaring
296 // variables or constants that exist in the prototype chain.
297 bool is_local = (*global == lookup.holder());
298 // Get the property attributes and determine if the property is
299 // read-only.
300 PropertyAttributes attributes = global->GetPropertyAttribute(*name);
301 bool is_read_only = (attributes & READ_ONLY) != 0;
302 if (lookup.type() == INTERCEPTOR) {
303 // If the interceptor says the property is there, we
304 // just return undefined without overwriting the property.
305 // Otherwise, we continue to setting the property.
306 if (attributes != ABSENT) {
307 // Check if the existing property conflicts with regards to const.
308 if (is_local && (is_read_only || is_const_property)) {
309 const char* type = (is_read_only) ? "const" : "var";
310 return ThrowRedeclarationError(type, name);
311 };
312 // The property already exists without conflicting: Go to
313 // the next declaration.
314 continue;
315 }
316 // Fall-through and introduce the absent property by using
317 // SetProperty.
318 } else {
319 if (is_local && (is_read_only || is_const_property)) {
320 const char* type = (is_read_only) ? "const" : "var";
321 return ThrowRedeclarationError(type, name);
322 }
323 // The property already exists without conflicting: Go to
324 // the next declaration.
325 continue;
326 }
327 }
328 } else {
329 // Copy the function and update its context. Use it as value.
330 Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(value);
331 Handle<JSFunction> function =
332 Factory::NewFunctionFromBoilerplate(boilerplate, context);
333 value = function;
334 }
335
336 LookupResult lookup;
337 global->LocalLookup(*name, &lookup);
338
339 PropertyAttributes attributes = is_const_property
340 ? static_cast<PropertyAttributes>(base | READ_ONLY)
341 : base;
342
343 if (lookup.IsProperty()) {
344 // There's a local property that we need to overwrite because
345 // we're either declaring a function or there's an interceptor
346 // that claims the property is absent.
347
348 // Check for conflicting re-declarations. We cannot have
349 // conflicting types in case of intercepted properties because
350 // they are absent.
351 if (lookup.type() != INTERCEPTOR &&
352 (lookup.IsReadOnly() || is_const_property)) {
353 const char* type = (lookup.IsReadOnly()) ? "const" : "var";
354 return ThrowRedeclarationError(type, name);
355 }
356 SetProperty(global, name, value, attributes);
357 } else {
358 // If a property with this name does not already exist on the
359 // global object add the property locally. We take special
360 // precautions to always add it as a local property even in case
361 // of callbacks in the prototype chain (this rules out using
362 // SetProperty). Also, we must use the handle-based version to
363 // avoid GC issues.
364 AddProperty(global, name, value, attributes);
365 }
366 }
367 // Done.
368 return Heap::undefined_value();
369}
370
371
372static Object* Runtime_DeclareContextSlot(Arguments args) {
373 HandleScope scope;
374 ASSERT(args.length() == 5);
375
376 // args[0] is result (TOS)
377 CONVERT_ARG_CHECKED(Context, context, 1);
378 Handle<String> name(String::cast(args[2]));
379 PropertyAttributes mode =
380 static_cast<PropertyAttributes>(Smi::cast(args[3])->value());
381 ASSERT(mode == READ_ONLY || mode == NONE);
382 Handle<Object> initial_value(args[4]);
383
384 // Declarations are always done in the function context.
385 context = Handle<Context>(context->fcontext());
386
387 int index;
388 PropertyAttributes attributes;
389 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
390 Handle<Object> context_obj =
391 context->Lookup(name, flags, &index, &attributes);
392
393 if (attributes != ABSENT) {
394 // The name was declared before; check for conflicting
395 // re-declarations: This is similar to the code in parser.cc in
396 // the AstBuildingParser::Declare function.
397 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
398 // Functions are not read-only.
399 ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
400 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
401 return ThrowRedeclarationError(type, name);
402 }
403
404 // Initialize it if necessary.
405 if (*initial_value != NULL) {
406 if (index >= 0) {
407 // The variable or constant context slot should always be in
408 // the function context; not in any outer context nor in the
409 // arguments object.
410 ASSERT(context_obj.is_identical_to(context));
411 if (((attributes & READ_ONLY) == 0) ||
412 context->get(index)->IsTheHole()) {
413 context->set(index, *initial_value);
414 }
415 } else {
416 // Slow case: The property is not in the FixedArray part of the context.
417 Handle<JSObject> context_ext = Handle<JSObject>::cast(context_obj);
418 SetProperty(context_ext, name, initial_value, mode);
419 }
420 }
421 return args[0]; // return TOS
422 }
423
424 // The property is not in the function context. It needs to be "declared"
425 // in the function context's extension context, or in the global context.
426 Handle<JSObject> context_ext;
427 if (context->extension() != NULL) {
428 // The function context's extension context exists - use it.
429 context_ext = Handle<JSObject>(context->extension());
430 } else {
431 // The function context's extension context does not exists - allocate it.
432 context_ext = Factory::NewJSObject(Top::context_extension_function());
433 // And store it in the extension slot.
434 context->set_extension(*context_ext);
435 }
436 ASSERT(*context_ext != NULL);
437
438 // Declare the property by setting it to the initial value if provided,
439 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
440 // constant declarations).
441 ASSERT(!context_ext->HasLocalProperty(*name));
442 Handle<Object> value(Heap::undefined_value());
443 if (*initial_value != NULL) value = initial_value;
444 SetProperty(context_ext, name, value, mode);
445 ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
446 return args[0]; // return TOS
447}
448
449
450static Object* Runtime_InitializeVarGlobal(Arguments args) {
451 NoHandleAllocation nha;
452
453 // Determine if we need to assign to the variable if it already
454 // exists (based on the number of arguments).
455 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
456 bool assign = args.length() == 2;
457
458 CONVERT_ARG_CHECKED(String, name, 0);
459 GlobalObject* global = Top::context()->global();
460
461 // According to ECMA-262, section 12.2, page 62, the property must
462 // not be deletable.
463 PropertyAttributes attributes = DONT_DELETE;
464
465 // Lookup the property locally in the global object. If it isn't
466 // there, we add the property and take special precautions to always
467 // add it as a local property even in case of callbacks in the
468 // prototype chain (this rules out using SetProperty).
469 LookupResult lookup;
470 global->LocalLookup(*name, &lookup);
471 if (!lookup.IsProperty()) {
472 Object* value = (assign) ? args[1] : Heap::undefined_value();
473 return global->AddProperty(*name, value, attributes);
474 }
475
476 // Determine if this is a redeclaration of something read-only.
477 if (lookup.IsReadOnly()) {
478 return ThrowRedeclarationError("const", name);
479 }
480
481 // Determine if this is a redeclaration of an intercepted read-only
482 // property and figure out if the property exists at all.
483 bool found = true;
484 PropertyType type = lookup.type();
485 if (type == INTERCEPTOR) {
486 PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
487 if (intercepted == ABSENT) {
488 // The interceptor claims the property isn't there. We need to
489 // make sure to introduce it.
490 found = false;
491 } else if ((intercepted & READ_ONLY) != 0) {
492 // The property is present, but read-only. Since we're trying to
493 // overwrite it with a variable declaration we must throw a
494 // re-declaration error.
495 return ThrowRedeclarationError("const", name);
496 }
497 // Restore global object from context (in case of GC).
498 global = Top::context()->global();
499 }
500
501 if (found && !assign) {
502 // The global property is there and we're not assigning any value
503 // to it. Just return.
504 return Heap::undefined_value();
505 }
506
507 // Assign the value (or undefined) to the property.
508 Object* value = (assign) ? args[1] : Heap::undefined_value();
509 return global->SetProperty(&lookup, *name, value, attributes);
510}
511
512
513static Object* Runtime_InitializeConstGlobal(Arguments args) {
514 // All constants are declared with an initial value. The name
515 // of the constant is the first argument and the initial value
516 // is the second.
517 RUNTIME_ASSERT(args.length() == 2);
518 CONVERT_ARG_CHECKED(String, name, 0);
519 Handle<Object> value = args.at<Object>(1);
520
521 // Get the current global object from top.
522 GlobalObject* global = Top::context()->global();
523
524 // According to ECMA-262, section 12.2, page 62, the property must
525 // not be deletable. Since it's a const, it must be READ_ONLY too.
526 PropertyAttributes attributes =
527 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
528
529 // Lookup the property locally in the global object. If it isn't
530 // there, we add the property and take special precautions to always
531 // add it as a local property even in case of callbacks in the
532 // prototype chain (this rules out using SetProperty).
533 LookupResult lookup;
534 global->LocalLookup(*name, &lookup);
535 if (!lookup.IsProperty()) {
536 return global->AddProperty(*name, *value, attributes);
537 }
538
539 // Determine if this is a redeclaration of something not
540 // read-only. In case the result is hidden behind an interceptor we
541 // need to ask it for the property attributes.
542 if (!lookup.IsReadOnly()) {
543 if (lookup.type() != INTERCEPTOR) {
544 return ThrowRedeclarationError("var", name);
545 }
546
547 PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
548
549 // Throw re-declaration error if the intercepted property is present
550 // but not read-only.
551 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
552 return ThrowRedeclarationError("var", name);
553 }
554
555 // Restore global object from context (in case of GC) and continue
556 // with setting the value because the property is either absent or
557 // read-only. We also have to do redo the lookup.
558 global = Top::context()->global();
559
560 // BUG 1213579: Handle the case where we have to set a read-only
561 // property through an interceptor and only do it if it's
562 // uninitialized, e.g. the hole. Nirk...
563 global->SetProperty(*name, *value, attributes);
564 return *value;
565 }
566
567 // Set the value, but only we're assigning the initial value to a
568 // constant. For now, we determine this by checking if the
569 // current value is the hole.
570 PropertyType type = lookup.type();
571 if (type == FIELD) {
572 FixedArray* properties = global->properties();
573 int index = lookup.GetFieldIndex();
574 if (properties->get(index)->IsTheHole()) {
575 properties->set(index, *value);
576 }
577 } else if (type == NORMAL) {
578 Dictionary* dictionary = global->property_dictionary();
579 int entry = lookup.GetDictionaryEntry();
580 if (dictionary->ValueAt(entry)->IsTheHole()) {
581 dictionary->ValueAtPut(entry, *value);
582 }
583 } else {
584 // Ignore re-initialization of constants that have already been
585 // assigned a function value.
586 ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
587 }
588
589 // Use the set value as the result of the operation.
590 return *value;
591}
592
593
594static Object* Runtime_InitializeConstContextSlot(Arguments args) {
595 HandleScope scope;
596 ASSERT(args.length() == 3);
597
598 Handle<Object> value(args[0]);
599 ASSERT(!value->IsTheHole());
600 CONVERT_ARG_CHECKED(Context, context, 1);
601 Handle<String> name(String::cast(args[2]));
602
603 // Initializations are always done in the function context.
604 context = Handle<Context>(context->fcontext());
605
606 int index;
607 PropertyAttributes attributes;
608 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
609 Handle<Object> context_obj =
610 context->Lookup(name, flags, &index, &attributes);
611
612 // The property should always be present. It is always declared
613 // before being initialized through DeclareContextSlot.
614 ASSERT(attributes != ABSENT && (attributes & READ_ONLY) != 0);
615
616 // If the slot is in the context, we set it but only if it hasn't
617 // been set before.
618 if (index >= 0) {
619 // The constant context slot should always be in the function
620 // context; not in any outer context nor in the arguments object.
621 ASSERT(context_obj.is_identical_to(context));
622 if (context->get(index)->IsTheHole()) {
623 context->set(index, *value);
624 }
625 return *value;
626 }
627
628 // Otherwise, the slot must be in a JS object extension.
629 Handle<JSObject> context_ext(JSObject::cast(*context_obj));
630
631 // We must initialize the value only if it wasn't initialized
632 // before, e.g. for const declarations in a loop. The property has
633 // the hole value if it wasn't initialized yet. NOTE: We cannot use
634 // GetProperty() to get the current value as it 'unholes' the value.
635 LookupResult lookup;
636 context_ext->LocalLookupRealNamedProperty(*name, &lookup);
637 ASSERT(lookup.IsProperty()); // the property was declared
638 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
639
640 PropertyType type = lookup.type();
641 if (type == FIELD) {
642 FixedArray* properties = context_ext->properties();
643 int index = lookup.GetFieldIndex();
644 if (properties->get(index)->IsTheHole()) {
645 properties->set(index, *value);
646 }
647 } else if (type == NORMAL) {
648 Dictionary* dictionary = context_ext->property_dictionary();
649 int entry = lookup.GetDictionaryEntry();
650 if (dictionary->ValueAt(entry)->IsTheHole()) {
651 dictionary->ValueAtPut(entry, *value);
652 }
653 } else {
654 // We should not reach here. Any real, named property should be
655 // either a field or a dictionary slot.
656 UNREACHABLE();
657 }
658 return *value;
659}
660
661
662static Object* Runtime_RegExpExec(Arguments args) {
663 HandleScope scope;
664 ASSERT(args.length() == 3);
665 CONVERT_CHECKED(JSValue, raw_regexp, args[0]);
666 Handle<JSValue> regexp(raw_regexp);
667 CONVERT_CHECKED(String, raw_subject, args[1]);
668 Handle<String> subject(raw_subject);
669 Handle<Object> index(args[2]);
670 ASSERT(index->IsNumber());
671 return *RegExpImpl::JsreExec(regexp, subject, index);
672}
673
674
675static Object* Runtime_RegExpExecGlobal(Arguments args) {
676 HandleScope scope;
677 ASSERT(args.length() == 2);
678 CONVERT_CHECKED(JSValue, raw_regexp, args[0]);
679 Handle<JSValue> regexp(raw_regexp);
680 CONVERT_CHECKED(String, raw_subject, args[1]);
681 Handle<String> subject(raw_subject);
682 return *RegExpImpl::JsreExecGlobal(regexp, subject);
683}
684
685
686static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
687 HandleScope scope;
688 ASSERT(args.length() == 4);
689 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
690 int index = Smi::cast(args[1])->value();
691 Handle<String> pattern = args.at<String>(2);
692 Handle<String> flags = args.at<String>(3);
693
694 // Compute the regular expression literal.
695 bool has_pending_exception;
696 Handle<Object> regexp =
697 RegExpImpl::CreateRegExpLiteral(pattern, flags, &has_pending_exception);
698 if (has_pending_exception) {
699 ASSERT(Top::has_pending_exception());
700 return Failure::Exception();
701 }
702 literals->set(index, *regexp);
703 return *regexp;
704}
705
706
707static Object* Runtime_FunctionGetName(Arguments args) {
708 NoHandleAllocation ha;
709 ASSERT(args.length() == 1);
710
711 CONVERT_CHECKED(JSFunction, f, args[0]);
712 return f->shared()->name();
713}
714
715
716static Object* Runtime_FunctionGetScript(Arguments args) {
717 HandleScope scope;
718 ASSERT(args.length() == 1);
719
720 CONVERT_CHECKED(JSFunction, fun, args[0]);
721 Handle<Object> script = Handle<Object>(fun->shared()->script());
722 if (!script->IsScript()) return Heap::undefined_value();
723
724 return *GetScriptWrapper(Handle<Script>::cast(script));
725}
726
727
728static Object* Runtime_FunctionGetSourceCode(Arguments args) {
729 NoHandleAllocation ha;
730 ASSERT(args.length() == 1);
731
732 CONVERT_CHECKED(JSFunction, f, args[0]);
733 return f->shared()->GetSourceCode();
734}
735
736
737static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) {
738 NoHandleAllocation ha;
739 ASSERT(args.length() == 1);
740
741 CONVERT_CHECKED(JSFunction, fun, args[0]);
742 int pos = fun->shared()->start_position();
743 return Smi::FromInt(pos);
744}
745
746
747static Object* Runtime_FunctionSetInstanceClassName(Arguments args) {
748 NoHandleAllocation ha;
749 ASSERT(args.length() == 2);
750
751 CONVERT_CHECKED(JSFunction, fun, args[0]);
752 CONVERT_CHECKED(String, name, args[1]);
753 fun->SetInstanceClassName(name);
754 return Heap::undefined_value();
755}
756
757
758static Object* Runtime_FunctionSetLength(Arguments args) {
759 NoHandleAllocation ha;
760 ASSERT(args.length() == 2);
761
762 CONVERT_CHECKED(JSFunction, fun, args[0]);
763 CONVERT_CHECKED(Smi, length, args[1]);
764 fun->shared()->set_length(length->value());
765 return length;
766}
767
768
769static Object* Runtime_FunctionSetPrototype(Arguments args) {
770 HandleScope scope;
771 ASSERT(args.length() == 2);
772
773 CONVERT_CHECKED(JSFunction, fun, args[0]);
774 Accessors::FunctionSetPrototype(fun, args[1], NULL);
775 return args[0]; // return TOS
776}
777
778
779static Object* Runtime_SetCode(Arguments args) {
780 HandleScope scope;
781 ASSERT(args.length() == 2);
782
783 CONVERT_CHECKED(JSFunction, raw_target, args[0]);
784 Handle<JSFunction> target(raw_target);
785 Handle<Object> code = args.at<Object>(1);
786
787 Handle<Context> context(target->context());
788
789 if (!code->IsNull()) {
790 RUNTIME_ASSERT(code->IsJSFunction());
791 Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
792 SetExpectedNofProperties(target, fun->shared()->expected_nof_properties());
793 if (!fun->is_compiled() && !CompileLazy(fun, KEEP_EXCEPTION)) {
794 return Failure::Exception();
795 }
796 // Set the code, formal parameter count, and the length of the target
797 // function.
798 target->set_code(fun->code());
799 target->shared()->set_length(fun->shared()->length());
800 target->shared()->set_formal_parameter_count(
801 fun->shared()->formal_parameter_count());
802 context = Handle<Context>(fun->context());
803
804 // Make sure we get a fresh copy of the literal vector to avoid
805 // cross context contamination.
806 int number_of_literals = fun->literals()->length();
807 if (number_of_literals > 0) {
808 Handle<FixedArray> literals =
809 Factory::NewFixedArray(number_of_literals, TENURED);
810 target->set_literals(*literals);
811 }
812 }
813
814 target->set_context(*context);
815 return *target;
816}
817
818
819static Object* CharCodeAt(String* subject, Object* index) {
820 uint32_t i = 0;
821 if (!Array::IndexFromObject(index, &i))
822 return Heap::nan_value();
823 // Flatten the string. If someone wants to get a char at an index
824 // in a cons string, it is likely that more indices will be
825 // accessed.
826 subject->TryFlatten();
827 if (i >= static_cast<uint32_t>(subject->length()))
828 return Heap::nan_value();
829 return Smi::FromInt(subject->Get(i));
830}
831
832
833static Object* Runtime_StringCharCodeAt(Arguments args) {
834 NoHandleAllocation ha;
835 ASSERT(args.length() == 2);
836
837 CONVERT_CHECKED(String, subject, args[0]);
838 Object* index = args[1];
839 return CharCodeAt(subject, index);
840}
841
842
843static Object* Runtime_CharFromCode(Arguments args) {
844 NoHandleAllocation ha;
845 ASSERT(args.length() == 1);
846 uint32_t code;
847 if (Array::IndexFromObject(args[0], &code)) {
848 if (code <= 0xffff) {
849 return Heap::LookupSingleCharacterStringFromCode(code);
850 }
851 }
852 return Heap::empty_string();
853}
854
855
856static inline void ComputeKMPNextTable(String* pattern, int next_table[]) {
857 int i = 0;
858 int j = -1;
859 next_table[0] = -1;
860
861 Access<StringInputBuffer> buffer(&string_input_buffer);
862 buffer->Reset(pattern);
863 int length = pattern->length();
864 uint16_t p = buffer->GetNext();
865 while (i < length - 1) {
866 while (j > -1 && p != pattern->Get(j)) {
867 j = next_table[j];
868 }
869 i++;
870 j++;
871 p = buffer->GetNext();
872 if (p == pattern->Get(j)) {
873 next_table[i] = next_table[j];
874 } else {
875 next_table[i] = j;
876 }
877 }
878}
879
880
881static Object* Runtime_StringIndexOf(Arguments args) {
882 NoHandleAllocation ha;
883 ASSERT(args.length() == 3);
884
885 CONVERT_CHECKED(String, sub, args[0]);
886 CONVERT_CHECKED(String, pat, args[1]);
887 Object* index = args[2];
888
889 int subject_length = sub->length();
890 int pattern_length = pat->length();
891
892 sub->TryFlatten();
893 pat->TryFlatten();
894
895 uint32_t start_index;
896 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
897 if (pattern_length == 0) return Smi::FromInt(start_index);
898
899 // Searching for one specific character is common. For one
900 // character patterns the KMP algorithm is guaranteed to slow down
901 // the search, so we just run through the subject string.
902 if (pattern_length == 1) {
903 uint16_t pattern_char = pat->Get(0);
904 for (int i = start_index; i < subject_length; i++) {
905 if (sub->Get(i) == pattern_char) {
906 return Smi::FromInt(i);
907 }
908 }
909 return Smi::FromInt(-1);
910 }
911
912 // For patterns with a length larger than one character we use the KMP
913 // algorithm.
914 //
915 // Compute the 'next' table.
916 int* next_table = NewArray<int>(pattern_length);
917 ComputeKMPNextTable(pat, next_table);
918 // Search using the 'next' table.
919 int pattern_index = 0;
920 // We would like to use StringInputBuffer here, but it does not have
921 // the ability to start anywhere but the first character of a
922 // string. It would be nice to have efficient forward-seeking
923 // support on StringInputBuffers.
924 int subject_index = start_index;
925 while (subject_index < subject_length) {
926 uint16_t subject_char = sub->Get(subject_index);
927 while (pattern_index > -1 && pat->Get(pattern_index) != subject_char) {
928 pattern_index = next_table[pattern_index];
929 }
930 pattern_index++;
931 subject_index++;
932 if (pattern_index >= pattern_length) {
933 DeleteArray(next_table);
934 return Smi::FromInt(subject_index - pattern_index);
935 }
936 }
937 DeleteArray(next_table);
938 return Smi::FromInt(-1);
939}
940
941
942static Object* Runtime_StringLastIndexOf(Arguments args) {
943 NoHandleAllocation ha;
944 ASSERT(args.length() == 3);
945
946 CONVERT_CHECKED(String, sub, args[0]);
947 CONVERT_CHECKED(String, pat, args[1]);
948 Object* index = args[2];
949
950 sub->TryFlatten();
951 pat->TryFlatten();
952
953 uint32_t start_index;
954 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
955
956 uint32_t pattern_length = pat->length();
957 uint32_t sub_length = sub->length();
958
959 if (start_index + pattern_length > sub_length)
960 start_index = sub_length - pattern_length;
961
962 for (int i = start_index; i >= 0; i--) {
963 bool found = true;
964 for (uint32_t j = 0; j < pattern_length; j++) {
965 if (sub->Get(i + j) != pat->Get(j)) {
966 found = false;
967 break;
968 }
969 }
970 if (found) return Smi::FromInt(i);
971 }
972
973 return Smi::FromInt(-1);
974}
975
976
977static Object* Runtime_StringLocaleCompare(Arguments args) {
978 NoHandleAllocation ha;
979 ASSERT(args.length() == 2);
980
981 CONVERT_CHECKED(String, str1, args[0]);
982 CONVERT_CHECKED(String, str2, args[1]);
983
984 if (str1 == str2) return Smi::FromInt(0); // Equal.
985 int str1_length = str1->length();
986 int str2_length = str2->length();
987
988 // Decide trivial cases without flattening.
989 if (str1_length == 0) {
990 if (str2_length == 0) return Smi::FromInt(0); // Equal.
991 return Smi::FromInt(-str2_length);
992 } else {
993 if (str2_length == 0) return Smi::FromInt(str1_length);
994 }
995
996 int end = str1_length < str2_length ? str1_length : str2_length;
997
998 // No need to flatten if we are going to find the answer on the first
999 // character. At this point we know there is at least one character
1000 // in each string, due to the trivial case handling above.
1001 int d = str1->Get(0) - str2->Get(0);
1002 if (d != 0) return Smi::FromInt(d);
1003
1004 str1->TryFlatten();
1005 str2->TryFlatten();
1006
1007 static StringInputBuffer buf1;
1008 static StringInputBuffer buf2;
1009
1010 buf1.Reset(str1);
1011 buf2.Reset(str2);
1012
1013 for (int i = 0; i < end; i++) {
1014 uint16_t char1 = buf1.GetNext();
1015 uint16_t char2 = buf2.GetNext();
1016 if (char1 != char2) return Smi::FromInt(char1 - char2);
1017 }
1018
1019 return Smi::FromInt(str1_length - str2_length);
1020}
1021
1022
1023static Object* Runtime_StringSlice(Arguments args) {
1024 NoHandleAllocation ha;
1025 ASSERT(args.length() == 3);
1026
1027 CONVERT_CHECKED(String, value, args[0]);
1028 CONVERT_DOUBLE_CHECKED(from_number, args[1]);
1029 CONVERT_DOUBLE_CHECKED(to_number, args[2]);
1030
1031 int start = FastD2I(from_number);
1032 int end = FastD2I(to_number);
1033
1034 RUNTIME_ASSERT(end >= start);
1035 RUNTIME_ASSERT(start >= 0);
1036 RUNTIME_ASSERT(end <= value->length());
1037 return value->Slice(start, end);
1038}
1039
1040
1041static Object* Runtime_NumberToRadixString(Arguments args) {
1042 NoHandleAllocation ha;
1043 ASSERT(args.length() == 2);
1044
1045 CONVERT_DOUBLE_CHECKED(value, args[0]);
1046 if (isnan(value)) {
1047 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1048 }
1049 if (isinf(value)) {
1050 if (value < 0) {
1051 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1052 }
1053 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1054 }
1055 CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
1056 int radix = FastD2I(radix_number);
1057 RUNTIME_ASSERT(2 <= radix && radix <= 36);
1058 char* str = DoubleToRadixCString(value, radix);
1059 Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
1060 DeleteArray(str);
1061 return result;
1062}
1063
1064
1065static Object* Runtime_NumberToFixed(Arguments args) {
1066 NoHandleAllocation ha;
1067 ASSERT(args.length() == 2);
1068
1069 CONVERT_DOUBLE_CHECKED(value, args[0]);
1070 if (isnan(value)) {
1071 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1072 }
1073 if (isinf(value)) {
1074 if (value < 0) {
1075 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1076 }
1077 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1078 }
1079 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
1080 int f = FastD2I(f_number);
1081 RUNTIME_ASSERT(f >= 0);
1082 char* str = DoubleToFixedCString(value, f);
1083 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1084 DeleteArray(str);
1085 return res;
1086}
1087
1088
1089static Object* Runtime_NumberToExponential(Arguments args) {
1090 NoHandleAllocation ha;
1091 ASSERT(args.length() == 2);
1092
1093 CONVERT_DOUBLE_CHECKED(value, args[0]);
1094 if (isnan(value)) {
1095 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1096 }
1097 if (isinf(value)) {
1098 if (value < 0) {
1099 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1100 }
1101 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1102 }
1103 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
1104 int f = FastD2I(f_number);
1105 RUNTIME_ASSERT(f >= -1 && f <= 20);
1106 char* str = DoubleToExponentialCString(value, f);
1107 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1108 DeleteArray(str);
1109 return res;
1110}
1111
1112
1113static Object* Runtime_NumberToPrecision(Arguments args) {
1114 NoHandleAllocation ha;
1115 ASSERT(args.length() == 2);
1116
1117 CONVERT_DOUBLE_CHECKED(value, args[0]);
1118 if (isnan(value)) {
1119 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1120 }
1121 if (isinf(value)) {
1122 if (value < 0) {
1123 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1124 }
1125 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1126 }
1127 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
1128 int f = FastD2I(f_number);
1129 RUNTIME_ASSERT(f >= 1 && f <= 21);
1130 char* str = DoubleToPrecisionCString(value, f);
1131 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1132 DeleteArray(str);
1133 return res;
1134}
1135
1136
1137// Returns a single character string where first character equals
1138// string->Get(index).
1139static Object* GetCharAt(String* string, uint32_t index) {
1140 if (index < static_cast<uint32_t>(string->length())) {
1141 string->TryFlatten();
1142 return Heap::LookupSingleCharacterStringFromCode(string->Get(index));
1143 }
1144 return *Execution::CharAt(Handle<String>(string), index);
1145}
1146
1147
1148Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
1149 // Handle [] indexing on Strings
1150 if (object->IsString()) {
1151 Object* result = GetCharAt(String::cast(*object), index);
1152 if (!result->IsUndefined()) return result;
1153 }
1154
1155 // Handle [] indexing on String objects
1156 if (object->IsStringObjectWithCharacterAt(index)) {
1157 JSValue* js_value = JSValue::cast(*object);
1158 Object* result = GetCharAt(String::cast(js_value->value()), index);
1159 if (!result->IsUndefined()) return result;
1160 }
1161
1162 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
1163 Object* prototype = object->GetPrototype();
1164 return prototype->GetElement(index);
1165 }
1166
1167 return object->GetElement(index);
1168}
1169
1170
1171Object* Runtime::GetObjectProperty(Handle<Object> object, Object* key) {
1172 if (object->IsUndefined() || object->IsNull()) {
1173 HandleScope scope;
1174 Handle<Object> key_handle(key);
1175 Handle<Object> args[2] = { key_handle, object };
1176 Handle<Object> error =
1177 Factory::NewTypeError("non_object_property_load",
1178 HandleVector(args, 2));
1179 return Top::Throw(*error);
1180 }
1181
1182 // Check if the given key is an array index.
1183 uint32_t index;
1184 if (Array::IndexFromObject(key, &index)) {
1185 HandleScope scope;
1186 return GetElementOrCharAt(object, index);
1187 }
1188
1189 // Convert the key to a string - possibly by calling back into JavaScript.
1190 String* name;
1191 if (key->IsString()) {
1192 name = String::cast(key);
1193 } else {
1194 HandleScope scope;
1195 bool has_pending_exception = false;
1196 Handle<Object> converted =
1197 Execution::ToString(Handle<Object>(key), &has_pending_exception);
1198 if (has_pending_exception) return Failure::Exception();
1199 name = String::cast(*converted);
1200 }
1201
1202 // Check if the name is trivially convertable to an index and get
1203 // the element if so.
1204 if (name->AsArrayIndex(&index)) {
1205 HandleScope scope;
1206 return GetElementOrCharAt(object, index);
1207 } else {
1208 PropertyAttributes attr;
1209 return object->GetProperty(name, &attr);
1210 }
1211}
1212
1213
1214static Object* Runtime_GetProperty(Arguments args) {
1215 NoHandleAllocation ha;
1216 ASSERT(args.length() == 2);
1217
1218 Handle<Object> object = args.at<Object>(0);
1219 Object* key = args[1];
1220
1221 return Runtime::GetObjectProperty(object, key);
1222}
1223
1224
1225Object* Runtime::SetObjectProperty(Handle<Object> object,
1226 Handle<Object> key,
1227 Handle<Object> value,
1228 PropertyAttributes attr) {
1229 if (object->IsUndefined() || object->IsNull()) {
1230 HandleScope scope;
1231 Handle<Object> obj(object);
1232 Handle<Object> args[2] = { key, obj };
1233 Handle<Object> error =
1234 Factory::NewTypeError("non_object_property_store",
1235 HandleVector(args, 2));
1236 return Top::Throw(*error);
1237 }
1238
1239 // If the object isn't a JavaScript object, we ignore the store.
1240 if (!object->IsJSObject()) return *value;
1241
1242 // Check if the given key is an array index.
1243 uint32_t index;
1244 if (Array::IndexFromObject(*key, &index)) {
1245 ASSERT(attr == NONE);
1246
1247 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
1248 // of a string using [] notation. We need to support this too in
1249 // JavaScript.
1250 // In the case of a String object we just need to redirect the assignment to
1251 // the underlying string if the index is in range. Since the underlying
1252 // string does nothing with the assignment then we can ignore such
1253 // assignments.
1254 if (object->IsStringObjectWithCharacterAt(index))
1255 return *value;
1256
1257 Object* result = JSObject::cast(*object)->SetElement(index, *value);
1258 if (result->IsFailure()) return result;
1259 return *value;
1260 }
1261
1262 if (key->IsString()) {
1263 Object* result;
1264 if (String::cast(*key)->AsArrayIndex(&index)) {
1265 ASSERT(attr == NONE);
1266 result = JSObject::cast(*object)->SetElement(index, *value);
1267 } else {
1268 String::cast(*key)->TryFlatten();
1269 result =
1270 JSObject::cast(*object)->SetProperty(String::cast(*key), *value,
1271 attr);
1272 }
1273 if (result->IsFailure()) return result;
1274 return *value;
1275 }
1276
1277 // Handlify object and value before calling into JavaScript again.
1278 Handle<JSObject> object_handle = Handle<JSObject>::cast(object);
1279 Handle<Object> value_handle = value;
1280
1281 // Call-back into JavaScript to convert the key to a string.
1282 HandleScope scope;
1283 bool has_pending_exception = false;
1284 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
1285 if (has_pending_exception) return Failure::Exception();
1286 Handle<String> name = Handle<String>::cast(converted);
1287
1288 if (name->AsArrayIndex(&index)) {
1289 ASSERT(attr == NONE);
1290 return object_handle->SetElement(index, *value_handle);
1291 } else {
1292 return object_handle->SetProperty(*name, *value_handle, attr);
1293 }
1294}
1295
1296
1297static Object* Runtime_AddProperty(Arguments args) {
1298 NoHandleAllocation ha;
1299 ASSERT(args.length() == 4);
1300
1301 CONVERT_CHECKED(JSObject, object, args[0]);
1302 CONVERT_CHECKED(String, name, args[1]);
1303 RUNTIME_ASSERT(!object->HasLocalProperty(name));
1304 CONVERT_CHECKED(Smi, attr_obj, args[3]);
1305
1306 int attr = attr_obj->value();
1307 RUNTIME_ASSERT((attr & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
1308 PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
1309
1310 return object->AddProperty(name, args[2], attributes);
1311}
1312
1313
1314static Object* Runtime_SetProperty(Arguments args) {
1315 NoHandleAllocation ha;
1316 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
1317
1318 Handle<Object> object = args.at<Object>(0);
1319 Handle<Object> key = args.at<Object>(1);
1320 Handle<Object> value = args.at<Object>(2);
1321
1322 // Compute attributes.
1323 PropertyAttributes attributes = NONE;
1324 if (args.length() == 4) {
1325 CONVERT_CHECKED(Smi, value_obj, args[3]);
1326 int value = value_obj->value();
1327 // Only attribute bits should be set.
1328 ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
1329 attributes = static_cast<PropertyAttributes>(value);
1330 }
1331 return Runtime::SetObjectProperty(object, key, value, attributes);
1332}
1333
1334
1335// Set a local property, even if it is READ_ONLY. If the property does not
1336// exist, it will be added with attributes NONE.
1337static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
1338 NoHandleAllocation ha;
1339 ASSERT(args.length() == 3);
1340
1341 CONVERT_CHECKED(JSObject, object, args[0]);
1342 CONVERT_CHECKED(String, name, args[1]);
1343
1344 return object->IgnoreAttributesAndSetLocalProperty(name, args[2]);
1345}
1346
1347
1348static Object* Runtime_DeleteProperty(Arguments args) {
1349 NoHandleAllocation ha;
1350 ASSERT(args.length() == 2);
1351
1352 CONVERT_CHECKED(JSObject, object, args[0]);
1353 CONVERT_CHECKED(String, key, args[1]);
1354 return object->DeleteProperty(key);
1355}
1356
1357
1358static Object* Runtime_HasLocalProperty(Arguments args) {
1359 NoHandleAllocation ha;
1360 ASSERT(args.length() == 2);
1361 CONVERT_CHECKED(String, key, args[1]);
1362
1363 // Only JS objects can have properties.
1364 if (args[0]->IsJSObject()) {
1365 JSObject* object = JSObject::cast(args[0]);
1366 if (object->HasLocalProperty(key)) return Heap::true_value();
1367 } else if (args[0]->IsString()) {
1368 // Well, there is one exception: Handle [] on strings.
1369 uint32_t index;
1370 if (key->AsArrayIndex(&index)) {
1371 String* string = String::cast(args[0]);
1372 if (index < static_cast<uint32_t>(string->length()))
1373 return Heap::true_value();
1374 }
1375 }
1376 return Heap::false_value();
1377}
1378
1379
1380static Object* Runtime_HasProperty(Arguments args) {
1381 NoHandleAllocation na;
1382 ASSERT(args.length() == 2);
1383
1384 // Only JS objects can have properties.
1385 if (args[0]->IsJSObject()) {
1386 JSObject* object = JSObject::cast(args[0]);
1387 CONVERT_CHECKED(String, key, args[1]);
1388 if (object->HasProperty(key)) return Heap::true_value();
1389 }
1390 return Heap::false_value();
1391}
1392
1393
1394static Object* Runtime_HasElement(Arguments args) {
1395 NoHandleAllocation na;
1396 ASSERT(args.length() == 2);
1397
1398 // Only JS objects can have elements.
1399 if (args[0]->IsJSObject()) {
1400 JSObject* object = JSObject::cast(args[0]);
1401 CONVERT_CHECKED(Smi, index_obj, args[1]);
1402 uint32_t index = index_obj->value();
1403 if (object->HasElement(index)) return Heap::true_value();
1404 }
1405 return Heap::false_value();
1406}
1407
1408
1409static Object* Runtime_IsPropertyEnumerable(Arguments args) {
1410 NoHandleAllocation ha;
1411 ASSERT(args.length() == 2);
1412
1413 CONVERT_CHECKED(JSObject, object, args[0]);
1414 CONVERT_CHECKED(String, key, args[1]);
1415
1416 uint32_t index;
1417 if (key->AsArrayIndex(&index)) {
1418 return Heap::ToBoolean(object->HasElement(index));
1419 }
1420
1421 LookupResult result;
1422 object->LocalLookup(key, &result);
1423 if (!result.IsProperty()) return Heap::false_value();
1424 return Heap::ToBoolean(!result.IsDontEnum());
1425}
1426
1427
1428static Object* Runtime_GetPropertyNames(Arguments args) {
1429 HandleScope scope;
1430 ASSERT(args.length() == 1);
1431
1432 CONVERT_CHECKED(JSObject, raw_object, args[0]);
1433 Handle<JSObject> object(raw_object);
1434 return *GetKeysFor(object);
1435}
1436
1437
1438// Returns either a FixedArray as Runtime_GetPropertyNames,
1439// or, if the given object has an enum cache that contains
1440// all enumerable properties of the object and its prototypes
1441// have none, the map of the object. This is used to speed up
1442// the check for deletions during a for-in.
1443static Object* Runtime_GetPropertyNamesFast(Arguments args) {
1444 ASSERT(args.length() == 1);
1445
1446 CONVERT_CHECKED(JSObject, raw_object, args[0]);
1447
1448 if (raw_object->IsSimpleEnum()) return raw_object->map();
1449
1450 HandleScope scope;
1451 Handle<JSObject> object(raw_object);
1452 Handle<FixedArray> content = GetKeysInFixedArrayFor(object);
1453
1454 // Test again, since cache may have been built by preceding call.
1455 if (object->IsSimpleEnum()) return object->map();
1456
1457 return *content;
1458}
1459
1460
1461static Object* Runtime_GetArgumentsProperty(Arguments args) {
1462 NoHandleAllocation ha;
1463 ASSERT(args.length() == 1);
1464
1465 // Compute the frame holding the arguments.
1466 JavaScriptFrameIterator it;
1467 it.AdvanceToArgumentsFrame();
1468 JavaScriptFrame* frame = it.frame();
1469
1470 // Get the actual number of provided arguments.
1471 const uint32_t n = frame->GetProvidedParametersCount();
1472
1473 // Try to convert the key to an index. If successful and within
1474 // index return the the argument from the frame.
1475 uint32_t index;
1476 if (Array::IndexFromObject(args[0], &index) && index < n) {
1477 return frame->GetParameter(index);
1478 }
1479
1480 // Convert the key to a string.
1481 HandleScope scope;
1482 bool exception = false;
1483 Handle<Object> converted =
1484 Execution::ToString(args.at<Object>(0), &exception);
1485 if (exception) return Failure::Exception();
1486 Handle<String> key = Handle<String>::cast(converted);
1487
1488 // Try to convert the string key into an array index.
1489 if (key->AsArrayIndex(&index)) {
1490 if (index < n) {
1491 return frame->GetParameter(index);
1492 } else {
1493 return Top::initial_object_prototype()->GetElement(index);
1494 }
1495 }
1496
1497 // Handle special arguments properties.
1498 if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n);
1499 if (key->Equals(Heap::callee_symbol())) return frame->function();
1500
1501 // Lookup in the initial Object.prototype object.
1502 return Top::initial_object_prototype()->GetProperty(*key);
1503}
1504
1505
1506static Object* Runtime_ToBool(Arguments args) {
1507 NoHandleAllocation ha;
1508 ASSERT(args.length() == 1);
1509
1510 return args[0]->ToBoolean();
1511}
1512
1513
1514// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
1515// Possible optimizations: put the type string into the oddballs.
1516static Object* Runtime_Typeof(Arguments args) {
1517 NoHandleAllocation ha;
1518
1519 Object* obj = args[0];
1520 if (obj->IsNumber()) return Heap::number_symbol();
1521 HeapObject* heap_obj = HeapObject::cast(obj);
1522
1523 // typeof an undetectable object is 'undefined'
1524 if (heap_obj->map()->is_undetectable())
1525 return Heap::undefined_symbol();
1526
1527 InstanceType instance_type = heap_obj->map()->instance_type();
1528 if (instance_type < FIRST_NONSTRING_TYPE) {
1529 return Heap::string_symbol();
1530 }
1531
1532 switch (instance_type) {
1533 case ODDBALL_TYPE:
1534 if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
1535 return Heap::boolean_symbol();
1536 }
1537 if (heap_obj->IsNull()) {
1538 return Heap::object_symbol();
1539 }
1540 ASSERT(heap_obj->IsUndefined());
1541 return Heap::undefined_symbol();
1542 case JS_FUNCTION_TYPE:
1543 return Heap::function_symbol();
1544 default:
1545 // For any kind of object not handled above, the spec rule for
1546 // host objects gives that it is okay to return "object"
1547 return Heap::object_symbol();
1548 }
1549}
1550
1551
1552static Object* Runtime_StringToNumber(Arguments args) {
1553 NoHandleAllocation ha;
1554 ASSERT(args.length() == 1);
1555 CONVERT_CHECKED(String, subject, args[0]);
1556 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
1557}
1558
1559
1560static Object* Runtime_StringFromCharCodeArray(Arguments args) {
1561 NoHandleAllocation ha;
1562 ASSERT(args.length() == 1);
1563
1564 CONVERT_CHECKED(JSArray, codes, args[0]);
1565 int length = Smi::cast(codes->length())->value();
1566
1567 // Check if the string can be ASCII.
1568 int i;
1569 for (i = 0; i < length; i++) {
1570 Object* element = codes->GetElement(i);
1571 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
1572 if ((chr & 0xffff) > String::kMaxAsciiCharCode)
1573 break;
1574 }
1575
1576 Object* object = NULL;
1577 if (i == length) { // The string is ASCII.
1578 object = Heap::AllocateRawAsciiString(length);
1579 } else { // The string is not ASCII.
1580 object = Heap::AllocateRawTwoByteString(length);
1581 }
1582
1583 if (object->IsFailure()) return object;
1584 String* result = String::cast(object);
1585 for (int i = 0; i < length; i++) {
1586 Object* element = codes->GetElement(i);
1587 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
1588 result->Set(i, chr & 0xffff);
1589 }
1590 return result;
1591}
1592
1593
1594// kNotEscaped is generated by the following:
1595//
1596// #!/bin/perl
1597// for (my $i = 0; $i < 256; $i++) {
1598// print "\n" if $i % 16 == 0;
1599// my $c = chr($i);
1600// my $escaped = 1;
1601// $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
1602// print $escaped ? "0, " : "1, ";
1603// }
1604
1605
1606static bool IsNotEscaped(uint16_t character) {
1607 // Only for 8 bit characters, the rest are always escaped (in a different way)
1608 ASSERT(character < 256);
1609 static const char kNotEscaped[256] = {
1610 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1611 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1612 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
1613 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
1614 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1615 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1616 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1617 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1618 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1619 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1620 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1621 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1622 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1623 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1624 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1625 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1626 };
1627 return kNotEscaped[character] != 0;
1628}
1629
1630
1631static Object* Runtime_URIEscape(Arguments args) {
1632 const char hex_chars[] = "0123456789ABCDEF";
1633 NoHandleAllocation ha;
1634 ASSERT(args.length() == 1);
1635 CONVERT_CHECKED(String, source, args[0]);
1636
1637 source->TryFlatten();
1638
1639 int escaped_length = 0;
1640 int length = source->length();
1641 {
1642 Access<StringInputBuffer> buffer(&string_input_buffer);
1643 buffer->Reset(source);
1644 while (buffer->has_more()) {
1645 uint16_t character = buffer->GetNext();
1646 if (character >= 256) {
1647 escaped_length += 6;
1648 } else if (IsNotEscaped(character)) {
1649 escaped_length++;
1650 } else {
1651 escaped_length += 3;
1652 }
1653 // We don't allow strings that are longer than Smi range.
1654 if (!Smi::IsValid(escaped_length)) {
1655 Top::context()->mark_out_of_memory();
1656 return Failure::OutOfMemoryException();
1657 }
1658 }
1659 }
1660 // No length change implies no change. Return original string if no change.
1661 if (escaped_length == length) {
1662 return source;
1663 }
1664 Object* o = Heap::AllocateRawAsciiString(escaped_length);
1665 if (o->IsFailure()) return o;
1666 String* destination = String::cast(o);
1667 int dest_position = 0;
1668
1669 Access<StringInputBuffer> buffer(&string_input_buffer);
1670 buffer->Rewind();
1671 while (buffer->has_more()) {
1672 uint16_t character = buffer->GetNext();
1673 if (character >= 256) {
1674 destination->Set(dest_position, '%');
1675 destination->Set(dest_position+1, 'u');
1676 destination->Set(dest_position+2, hex_chars[character >> 12]);
1677 destination->Set(dest_position+3, hex_chars[(character >> 8) & 0xf]);
1678 destination->Set(dest_position+4, hex_chars[(character >> 4) & 0xf]);
1679 destination->Set(dest_position+5, hex_chars[character & 0xf]);
1680 dest_position += 6;
1681 } else if (IsNotEscaped(character)) {
1682 destination->Set(dest_position, character);
1683 dest_position++;
1684 } else {
1685 destination->Set(dest_position, '%');
1686 destination->Set(dest_position+1, hex_chars[character >> 4]);
1687 destination->Set(dest_position+2, hex_chars[character & 0xf]);
1688 dest_position += 3;
1689 }
1690 }
1691 return destination;
1692}
1693
1694
1695static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
1696 static const signed char kHexValue['g'] = {
1697 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1698 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1699 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1700 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
1701 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1702 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1703 -1, 10, 11, 12, 13, 14, 15 };
1704
1705 if (character1 > 'f') return -1;
1706 int hi = kHexValue[character1];
1707 if (hi == -1) return -1;
1708 if (character2 > 'f') return -1;
1709 int lo = kHexValue[character2];
1710 if (lo == -1) return -1;
1711 return (hi << 4) + lo;
1712}
1713
1714
1715static inline int Unescape(String* source, int i, int length, int* step) {
1716 uint16_t character = source->Get(i);
1717 int32_t hi, lo;
1718 if (character == '%' &&
1719 i <= length - 6 &&
1720 source->Get(i + 1) == 'u' &&
1721 (hi = TwoDigitHex(source->Get(i + 2), source->Get(i + 3))) != -1 &&
1722 (lo = TwoDigitHex(source->Get(i + 4), source->Get(i + 5))) != -1) {
1723 *step = 6;
1724 return (hi << 8) + lo;
1725 } else if (character == '%' &&
1726 i <= length - 3 &&
1727 (lo = TwoDigitHex(source->Get(i + 1), source->Get(i + 2))) != -1) {
1728 *step = 3;
1729 return lo;
1730 } else {
1731 *step = 1;
1732 return character;
1733 }
1734}
1735
1736
1737static Object* Runtime_URIUnescape(Arguments args) {
1738 NoHandleAllocation ha;
1739 ASSERT(args.length() == 1);
1740 CONVERT_CHECKED(String, source, args[0]);
1741
1742 source->TryFlatten();
1743
1744 bool ascii = true;
1745 int length = source->length();
1746
1747 int unescaped_length = 0;
1748 for (int i = 0; i < length; unescaped_length++) {
1749 int step;
1750 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode)
1751 ascii = false;
1752 i += step;
1753 }
1754
1755 // No length change implies no change. Return original string if no change.
1756 if (unescaped_length == length)
1757 return source;
1758
1759 Object* o = ascii ?
1760 Heap::AllocateRawAsciiString(unescaped_length) :
1761 Heap::AllocateRawTwoByteString(unescaped_length);
1762 if (o->IsFailure()) return o;
1763 String* destination = String::cast(o);
1764
1765 int dest_position = 0;
1766 for (int i = 0; i < length; dest_position++) {
1767 int step;
1768 destination->Set(dest_position, Unescape(source, i, length, &step));
1769 i += step;
1770 }
1771 return destination;
1772}
1773
1774
1775static Object* Runtime_StringParseInt(Arguments args) {
1776 NoHandleAllocation ha;
1777
1778 CONVERT_CHECKED(String, s, args[0]);
1779 CONVERT_DOUBLE_CHECKED(n, args[1]);
1780 int radix = FastD2I(n);
1781
1782 s->TryFlatten();
1783
1784 int len = s->length();
1785 int i;
1786
1787 // Skip leading white space.
1788 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
1789 if (i == len) return Heap::nan_value();
1790
1791 // Compute the sign (default to +).
1792 int sign = 1;
1793 if (s->Get(i) == '-') {
1794 sign = -1;
1795 i++;
1796 } else if (s->Get(i) == '+') {
1797 i++;
1798 }
1799
1800 // Compute the radix if 0.
1801 if (radix == 0) {
1802 radix = 10;
1803 if (i < len && s->Get(i) == '0') {
1804 radix = 8;
1805 if (i + 1 < len) {
1806 int c = s->Get(i + 1);
1807 if (c == 'x' || c == 'X') {
1808 radix = 16;
1809 i += 2;
1810 }
1811 }
1812 }
1813 } else if (radix == 16) {
1814 // Allow 0x or 0X prefix if radix is 16.
1815 if (i + 1 < len && s->Get(i) == '0') {
1816 int c = s->Get(i + 1);
1817 if (c == 'x' || c == 'X') i += 2;
1818 }
1819 }
1820
1821 RUNTIME_ASSERT(2 <= radix && radix <= 36);
1822 double value;
1823 int end_index = StringToInt(s, i, radix, &value);
1824 if (end_index != i) {
1825 return Heap::NumberFromDouble(sign * value);
1826 }
1827 return Heap::nan_value();
1828}
1829
1830
1831static Object* Runtime_StringParseFloat(Arguments args) {
1832 NoHandleAllocation ha;
1833 CONVERT_CHECKED(String, str, args[0]);
1834
1835 // ECMA-262 section 15.1.2.3, empty string is NaN
1836 double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
1837
1838 // Create a number object from the value.
1839 return Heap::NumberFromDouble(value);
1840}
1841
1842
1843static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
1844static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
1845
1846
1847template <class Converter>
1848static Object* ConvertCase(Arguments args,
1849 unibrow::Mapping<Converter, 128> *mapping) {
1850 NoHandleAllocation ha;
1851
1852 CONVERT_CHECKED(String, s, args[0]);
1853 int raw_string_length = s->length();
1854 // Assume that the string is not empty; we need this assumption later
1855 if (raw_string_length == 0) return s;
1856 int length = raw_string_length;
1857
1858 s->TryFlatten();
1859
1860 // We try this twice, once with the assumption that the result is
1861 // no longer than the input and, if that assumption breaks, again
1862 // with the exact length. This is implemented using a goto back
1863 // to this label if we discover that the assumption doesn't hold.
1864 // I apologize sincerely for this and will give a vaffel-is to
1865 // anyone who can implement it in a nicer way.
1866 try_convert:
1867
1868 // Allocate the resulting string.
1869 //
1870 // NOTE: This assumes that the upper/lower case of an ascii
1871 // character is also ascii. This is currently the case, but it
1872 // might break in the future if we implement more context and locale
1873 // dependent upper/lower conversions.
1874 Object* o = s->IsAscii()
1875 ? Heap::AllocateRawAsciiString(length)
1876 : Heap::AllocateRawTwoByteString(length);
1877 if (o->IsFailure())
1878 return o;
1879 String* result = String::cast(o);
1880 bool has_changed_character = false;
1881
1882
1883 // Convert all characters to upper case, assuming that they will fit
1884 // in the buffer
1885 Access<StringInputBuffer> buffer(&string_input_buffer);
1886 buffer->Reset(s);
1887 unibrow::uchar chars[unibrow::kMaxCaseConvertedSize];
1888 int i = 0;
1889 // We can assume that the string is not empty
1890 uc32 current = buffer->GetNext();
1891 while (i < length) {
1892 uc32 next = buffer->has_more() ? buffer->GetNext() : 0;
1893 int char_length = mapping->get(current, next, chars);
1894 if (char_length == 0) {
1895 // The case conversion of this character is the character itself.
1896 result->Set(i, current);
1897 i++;
1898 } else if (char_length == 1) {
1899 // Common case: converting the letter resulted in one character.
1900 ASSERT(static_cast<uc32>(chars[0]) != current);
1901 result->Set(i, chars[0]);
1902 has_changed_character = true;
1903 i++;
1904 } else if (length == raw_string_length) {
1905 // We've assumed that the result would be as long as the
1906 // input but here is a character that converts to several
1907 // characters. No matter, we calculate the exact length
1908 // of the result and try the whole thing again.
1909 //
1910 // Note that this leaves room for optimization. We could just
1911 // memcpy what we already have to the result string. Also,
1912 // the result string is the last object allocated we could
1913 // "realloc" it and probably, in the vast majority of cases,
1914 // extend the existing string to be able to hold the full
1915 // result.
1916 int current_length = i + char_length + mapping->get(next, 0, chars);
1917 while (buffer->has_more()) {
1918 current = buffer->GetNext();
1919 int char_length = mapping->get(current, 0, chars);
1920 if (char_length == 0) char_length = 1;
1921 current += char_length;
1922 }
1923 length = current_length;
1924 goto try_convert;
1925 } else {
1926 for (int j = 0; j < char_length; j++) {
1927 result->Set(i, chars[j]);
1928 i++;
1929 }
1930 has_changed_character = true;
1931 }
1932 current = next;
1933 }
1934 if (has_changed_character) {
1935 return result;
1936 } else {
1937 // If we didn't actually change anything in doing the conversion
1938 // we simple return the result and let the converted string
1939 // become garbage; there is no reason to keep two identical strings
1940 // alive.
1941 return s;
1942 }
1943}
1944
1945
1946static Object* Runtime_StringToLowerCase(Arguments args) {
1947 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
1948}
1949
1950
1951static Object* Runtime_StringToUpperCase(Arguments args) {
1952 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
1953}
1954
1955
1956static Object* Runtime_ConsStringFst(Arguments args) {
1957 NoHandleAllocation ha;
1958
1959 CONVERT_CHECKED(ConsString, str, args[0]);
1960 return str->first();
1961}
1962
1963
1964static Object* Runtime_ConsStringSnd(Arguments args) {
1965 NoHandleAllocation ha;
1966
1967 CONVERT_CHECKED(ConsString, str, args[0]);
1968 return str->second();
1969}
1970
1971
1972static Object* Runtime_NumberToString(Arguments args) {
1973 NoHandleAllocation ha;
1974 ASSERT(args.length() == 1);
1975
1976 Object* number = args[0];
1977 RUNTIME_ASSERT(number->IsNumber());
1978
1979 Object* cached = Heap::GetNumberStringCache(number);
1980 if (cached != Heap::undefined_value()) {
1981 return cached;
1982 }
1983
1984 char arr[100];
1985 Vector<char> buffer(arr, ARRAY_SIZE(arr));
1986 const char* str;
1987 if (number->IsSmi()) {
1988 int num = Smi::cast(number)->value();
1989 str = IntToCString(num, buffer);
1990 } else {
1991 double num = HeapNumber::cast(number)->value();
1992 str = DoubleToCString(num, buffer);
1993 }
1994 Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
1995
1996 if (!result->IsFailure()) {
1997 Heap::SetNumberStringCache(number, String::cast(result));
1998 }
1999 return result;
2000}
2001
2002
2003static Object* Runtime_NumberToInteger(Arguments args) {
2004 NoHandleAllocation ha;
2005 ASSERT(args.length() == 1);
2006
2007 Object* obj = args[0];
2008
2009 if (obj->IsSmi())
2010 return obj;
2011
2012 CONVERT_DOUBLE_CHECKED(number, obj);
2013 return Heap::NumberFromDouble(DoubleToInteger(number));
2014}
2015
2016
2017static Object* Runtime_NumberToJSUint32(Arguments args) {
2018 NoHandleAllocation ha;
2019 ASSERT(args.length() == 1);
2020
2021 Object* obj = args[0];
2022 if (obj->IsSmi() && Smi::cast(obj)->value() >= 0) return obj;
2023 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, obj);
2024 return Heap::NumberFromUint32(number);
2025}
2026
2027
2028static Object* Runtime_NumberToJSInt32(Arguments args) {
2029 NoHandleAllocation ha;
2030 ASSERT(args.length() == 1);
2031
2032 Object* obj = args[0];
2033 if (obj->IsSmi()) return obj;
2034 CONVERT_DOUBLE_CHECKED(number, obj);
2035 return Heap::NumberFromInt32(DoubleToInt32(number));
2036}
2037
2038
2039static Object* Runtime_NumberAdd(Arguments args) {
2040 NoHandleAllocation ha;
2041 ASSERT(args.length() == 2);
2042
2043 CONVERT_DOUBLE_CHECKED(x, args[0]);
2044 CONVERT_DOUBLE_CHECKED(y, args[1]);
2045 return Heap::AllocateHeapNumber(x + y);
2046}
2047
2048
2049static Object* Runtime_NumberSub(Arguments args) {
2050 NoHandleAllocation ha;
2051 ASSERT(args.length() == 2);
2052
2053 CONVERT_DOUBLE_CHECKED(x, args[0]);
2054 CONVERT_DOUBLE_CHECKED(y, args[1]);
2055 return Heap::AllocateHeapNumber(x - y);
2056}
2057
2058
2059static Object* Runtime_NumberMul(Arguments args) {
2060 NoHandleAllocation ha;
2061 ASSERT(args.length() == 2);
2062
2063 CONVERT_DOUBLE_CHECKED(x, args[0]);
2064 CONVERT_DOUBLE_CHECKED(y, args[1]);
2065 return Heap::AllocateHeapNumber(x * y);
2066}
2067
2068
2069static Object* Runtime_NumberAlloc(Arguments args) {
2070 NoHandleAllocation ha;
2071 ASSERT(args.length() == 1);
2072 return Heap::AllocateHeapNumber(0);
2073}
2074
2075
2076static Object* Runtime_NumberUnaryMinus(Arguments args) {
2077 NoHandleAllocation ha;
2078 ASSERT(args.length() == 1);
2079
2080 CONVERT_DOUBLE_CHECKED(x, args[0]);
2081 return Heap::AllocateHeapNumber(-x);
2082}
2083
2084
2085static Object* Runtime_NumberDiv(Arguments args) {
2086 NoHandleAllocation ha;
2087 ASSERT(args.length() == 2);
2088
2089 CONVERT_DOUBLE_CHECKED(x, args[0]);
2090 CONVERT_DOUBLE_CHECKED(y, args[1]);
2091 return Heap::NewNumberFromDouble(x / y);
2092}
2093
2094
2095static Object* Runtime_NumberMod(Arguments args) {
2096 NoHandleAllocation ha;
2097 ASSERT(args.length() == 2);
2098
2099 CONVERT_DOUBLE_CHECKED(x, args[0]);
2100 CONVERT_DOUBLE_CHECKED(y, args[1]);
2101
2102#ifdef WIN32
2103 // Workaround MS fmod bugs. ECMA-262 says:
2104 // dividend is finite and divisor is an infinity => result equals dividend
2105 // dividend is a zero and divisor is nonzero finite => result equals dividend
2106 if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) &&
2107 !(x == 0 && (y != 0 && isfinite(y))))
2108#endif
2109 x = fmod(x, y);
2110 // NewNumberFromDouble may return a Smi instead of a Number object
2111 return Heap::NewNumberFromDouble(x);
2112}
2113
2114
2115static Object* Runtime_StringAdd(Arguments args) {
2116 NoHandleAllocation ha;
2117 ASSERT(args.length() == 2);
2118
2119 CONVERT_CHECKED(String, str1, args[0]);
2120 CONVERT_CHECKED(String, str2, args[1]);
2121 int len1 = str1->length();
2122 int len2 = str2->length();
2123 if (len1 == 0) return str2;
2124 if (len2 == 0) return str1;
2125 int length_sum = len1 + len2;
2126 // Make sure that an out of memory exception is thrown if the length
2127 // of the new cons string is too large to fit in a Smi.
2128 if (length_sum > Smi::kMaxValue || length_sum < 0) {
2129 Top::context()->mark_out_of_memory();
2130 return Failure::OutOfMemoryException();
2131 }
2132 return Heap::AllocateConsString(str1, str2);
2133}
2134
2135
2136static Object* Runtime_StringBuilderConcat(Arguments args) {
2137 NoHandleAllocation ha;
2138 ASSERT(args.length() == 2);
2139 CONVERT_CHECKED(JSArray, array, args[0]);
2140 CONVERT_CHECKED(String, special, args[1]);
2141 int special_length = special->length();
2142 Object* smi_array_length = array->length();
2143 if (!smi_array_length->IsSmi()) {
2144 Top::context()->mark_out_of_memory();
2145 return Failure::OutOfMemoryException();
2146 }
2147 int array_length = Smi::cast(smi_array_length)->value();
2148 if (!array->HasFastElements()) {
2149 return Top::Throw(Heap::illegal_argument_symbol());
2150 }
2151 FixedArray* fixed_array = FixedArray::cast(array->elements());
2152 if (fixed_array->length() < array_length)
2153 array_length = fixed_array->length();
2154
2155 if (array_length == 0) {
2156 return Heap::empty_string();
2157 } else if (array_length == 1) {
2158 Object* first = fixed_array->get(0);
2159 if (first->IsString()) return first;
2160 }
2161
2162 bool ascii = special->IsAscii();
2163 int position = 0;
2164 for (int i = 0; i < array_length; i++) {
2165 Object* elt = fixed_array->get(i);
2166 if (elt->IsSmi()) {
2167 int len = Smi::cast(elt)->value();
2168 int pos = len >> 11;
2169 len &= 0x7ff;
2170 if (pos + len > special_length) {
2171 return Top::Throw(Heap::illegal_argument_symbol());
2172 }
2173 position += len;
2174 } else if (elt->IsString()) {
2175 String* element = String::cast(elt);
2176 int element_length = element->length();
2177 if (!Smi::IsValid(element_length + position)) {
2178 Top::context()->mark_out_of_memory();
2179 return Failure::OutOfMemoryException();
2180 }
2181 position += element_length;
2182 if (ascii && !element->IsAscii())
2183 ascii = false;
2184 } else {
2185 return Top::Throw(Heap::illegal_argument_symbol());
2186 }
2187 }
2188
2189 int length = position;
2190 position = 0;
2191 Object* object;
2192 if (ascii) {
2193 object = Heap::AllocateRawAsciiString(length);
2194 } else {
2195 object = Heap::AllocateRawTwoByteString(length);
2196 }
2197 if (object->IsFailure()) return object;
2198
2199 String* answer = String::cast(object);
2200 for (int i = 0; i < array_length; i++) {
2201 Object* element = fixed_array->get(i);
2202 if (element->IsSmi()) {
2203 int len = Smi::cast(element)->value();
2204 int pos = len >> 11;
2205 len &= 0x7ff;
2206 String::Flatten(special, answer, pos, pos + len, position);
2207 position += len;
2208 } else {
2209 String* string = String::cast(element);
2210 int element_length = string->length();
2211 String::Flatten(string, answer, 0, element_length, position);
2212 position += element_length;
2213 }
2214 }
2215 return answer;
2216}
2217
2218
2219static Object* Runtime_NumberOr(Arguments args) {
2220 NoHandleAllocation ha;
2221 ASSERT(args.length() == 2);
2222
2223 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2224 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2225 return Heap::NumberFromInt32(x | y);
2226}
2227
2228
2229static Object* Runtime_NumberAnd(Arguments args) {
2230 NoHandleAllocation ha;
2231 ASSERT(args.length() == 2);
2232
2233 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2234 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2235 return Heap::NumberFromInt32(x & y);
2236}
2237
2238
2239static Object* Runtime_NumberXor(Arguments args) {
2240 NoHandleAllocation ha;
2241 ASSERT(args.length() == 2);
2242
2243 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2244 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2245 return Heap::NumberFromInt32(x ^ y);
2246}
2247
2248
2249static Object* Runtime_NumberNot(Arguments args) {
2250 NoHandleAllocation ha;
2251 ASSERT(args.length() == 1);
2252
2253 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2254 return Heap::NumberFromInt32(~x);
2255}
2256
2257
2258static Object* Runtime_NumberShl(Arguments args) {
2259 NoHandleAllocation ha;
2260 ASSERT(args.length() == 2);
2261
2262 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2263 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2264 return Heap::NumberFromInt32(x << (y & 0x1f));
2265}
2266
2267
2268static Object* Runtime_NumberShr(Arguments args) {
2269 NoHandleAllocation ha;
2270 ASSERT(args.length() == 2);
2271
2272 CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
2273 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2274 return Heap::NumberFromUint32(x >> (y & 0x1f));
2275}
2276
2277
2278static Object* Runtime_NumberSar(Arguments args) {
2279 NoHandleAllocation ha;
2280 ASSERT(args.length() == 2);
2281
2282 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2283 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2284 return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
2285}
2286
2287
2288static Object* Runtime_ObjectEquals(Arguments args) {
2289 NoHandleAllocation ha;
2290 ASSERT(args.length() == 2);
2291
2292 return Smi::FromInt(args[0] == args[1] ? EQUAL : NOT_EQUAL);
2293}
2294
2295
2296static Object* Runtime_NumberEquals(Arguments args) {
2297 NoHandleAllocation ha;
2298 ASSERT(args.length() == 2);
2299
2300 CONVERT_DOUBLE_CHECKED(x, args[0]);
2301 CONVERT_DOUBLE_CHECKED(y, args[1]);
2302 if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
2303 if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
2304 if (x == y) return Smi::FromInt(EQUAL);
2305 Object* result;
2306 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
2307 result = Smi::FromInt(EQUAL);
2308 } else {
2309 result = Smi::FromInt(NOT_EQUAL);
2310 }
2311 return result;
2312}
2313
2314
2315static Object* Runtime_StringEquals(Arguments args) {
2316 NoHandleAllocation ha;
2317 ASSERT(args.length() == 2);
2318
2319 CONVERT_CHECKED(String, x, args[0]);
2320 CONVERT_CHECKED(String, y, args[1]);
2321
2322 // This is very similar to String::Equals(String*) but that version
2323 // requires flattened strings as input, whereas we flatten the
2324 // strings only if the fast cases fail. Note that this may fail,
2325 // requiring a GC. String::Equals(String*) returns a bool and has
2326 // no way to signal a failure.
2327 if (y == x) return Smi::FromInt(EQUAL);
2328 if (x->IsSymbol() && y->IsSymbol()) return Smi::FromInt(NOT_EQUAL);
2329 // Compare contents
2330 int len = x->length();
2331 if (len != y->length()) return Smi::FromInt(NOT_EQUAL);
2332 if (len == 0) return Smi::FromInt(EQUAL);
2333 // Fast case: First, middle and last characters.
2334 if (x->Get(0) != y->Get(0)) return Smi::FromInt(NOT_EQUAL);
2335 if (x->Get(len>>1) != y->Get(len>>1)) return Smi::FromInt(NOT_EQUAL);
2336 if (x->Get(len - 1) != y->Get(len - 1)) return Smi::FromInt(NOT_EQUAL);
2337
2338 x->TryFlatten();
2339 y->TryFlatten();
2340
2341 static StringInputBuffer buf1;
2342 static StringInputBuffer buf2;
2343 buf1.Reset(x);
2344 buf2.Reset(y);
2345 while (buf1.has_more()) {
2346 if (buf1.GetNext() != buf2.GetNext())
2347 return Smi::FromInt(NOT_EQUAL);
2348 }
2349 return Smi::FromInt(EQUAL);
2350}
2351
2352
2353static Object* Runtime_NumberCompare(Arguments args) {
2354 NoHandleAllocation ha;
2355 ASSERT(args.length() == 3);
2356
2357 CONVERT_DOUBLE_CHECKED(x, args[0]);
2358 CONVERT_DOUBLE_CHECKED(y, args[1]);
2359 if (isnan(x) || isnan(y)) return args[2];
2360 if (x == y) return Smi::FromInt(EQUAL);
2361 if (isless(x, y)) return Smi::FromInt(LESS);
2362 return Smi::FromInt(GREATER);
2363}
2364
2365
2366static Object* Runtime_StringCompare(Arguments args) {
2367 NoHandleAllocation ha;
2368 ASSERT(args.length() == 2);
2369
2370 CONVERT_CHECKED(String, x, args[0]);
2371 CONVERT_CHECKED(String, y, args[1]);
2372
2373 // A few fast case tests before we flatten.
2374 if (x == y) return Smi::FromInt(EQUAL);
2375 if (y->length() == 0) {
2376 if (x->length() == 0)
2377 return Smi::FromInt(EQUAL);
2378 return Smi::FromInt(GREATER);
2379 } else if (x->length() == 0) {
2380 return Smi::FromInt(LESS);
2381 }
2382 {
2383 int d = x->Get(0) - y->Get(0);
2384 if (d < 0) return Smi::FromInt(LESS);
2385 else if (d > 0) return Smi::FromInt(GREATER);
2386 }
2387
2388 x->TryFlatten();
2389 y->TryFlatten();
2390
2391 static StringInputBuffer bufx;
2392 static StringInputBuffer bufy;
2393 bufx.Reset(x);
2394 bufy.Reset(y);
2395 while (bufx.has_more() && bufy.has_more()) {
2396 int d = bufx.GetNext() - bufy.GetNext();
2397 if (d < 0) return Smi::FromInt(LESS);
2398 else if (d > 0) return Smi::FromInt(GREATER);
2399 }
2400
2401 // x is (non-trivial) prefix of y:
2402 if (bufy.has_more()) return Smi::FromInt(LESS);
2403 // y is prefix of x:
2404 return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
2405}
2406
2407
2408static Object* Runtime_Math_abs(Arguments args) {
2409 NoHandleAllocation ha;
2410 ASSERT(args.length() == 1);
2411
2412 CONVERT_DOUBLE_CHECKED(x, args[0]);
2413 return Heap::AllocateHeapNumber(fabs(x));
2414}
2415
2416
2417static Object* Runtime_Math_acos(Arguments args) {
2418 NoHandleAllocation ha;
2419 ASSERT(args.length() == 1);
2420
2421 CONVERT_DOUBLE_CHECKED(x, args[0]);
2422 return Heap::AllocateHeapNumber(acos(x));
2423}
2424
2425
2426static Object* Runtime_Math_asin(Arguments args) {
2427 NoHandleAllocation ha;
2428 ASSERT(args.length() == 1);
2429
2430 CONVERT_DOUBLE_CHECKED(x, args[0]);
2431 return Heap::AllocateHeapNumber(asin(x));
2432}
2433
2434
2435static Object* Runtime_Math_atan(Arguments args) {
2436 NoHandleAllocation ha;
2437 ASSERT(args.length() == 1);
2438
2439 CONVERT_DOUBLE_CHECKED(x, args[0]);
2440 return Heap::AllocateHeapNumber(atan(x));
2441}
2442
2443
2444static Object* Runtime_Math_atan2(Arguments args) {
2445 NoHandleAllocation ha;
2446 ASSERT(args.length() == 2);
2447
2448 CONVERT_DOUBLE_CHECKED(x, args[0]);
2449 CONVERT_DOUBLE_CHECKED(y, args[1]);
2450 double result;
2451 if (isinf(x) && isinf(y)) {
2452 // Make sure that the result in case of two infinite arguments
2453 // is a multiple of Pi / 4. The sign of the result is determined
2454 // by the first argument (x) and the sign of the second argument
2455 // determines the multiplier: one or three.
2456 static double kPiDividedBy4 = 0.78539816339744830962;
2457 int multiplier = (x < 0) ? -1 : 1;
2458 if (y < 0) multiplier *= 3;
2459 result = multiplier * kPiDividedBy4;
2460 } else {
2461 result = atan2(x, y);
2462 }
2463 return Heap::AllocateHeapNumber(result);
2464}
2465
2466
2467static Object* Runtime_Math_ceil(Arguments args) {
2468 NoHandleAllocation ha;
2469 ASSERT(args.length() == 1);
2470
2471 CONVERT_DOUBLE_CHECKED(x, args[0]);
2472 return Heap::NumberFromDouble(ceiling(x));
2473}
2474
2475
2476static Object* Runtime_Math_cos(Arguments args) {
2477 NoHandleAllocation ha;
2478 ASSERT(args.length() == 1);
2479
2480 CONVERT_DOUBLE_CHECKED(x, args[0]);
2481 return Heap::AllocateHeapNumber(cos(x));
2482}
2483
2484
2485static Object* Runtime_Math_exp(Arguments args) {
2486 NoHandleAllocation ha;
2487 ASSERT(args.length() == 1);
2488
2489 CONVERT_DOUBLE_CHECKED(x, args[0]);
2490 return Heap::AllocateHeapNumber(exp(x));
2491}
2492
2493
2494static Object* Runtime_Math_floor(Arguments args) {
2495 NoHandleAllocation ha;
2496 ASSERT(args.length() == 1);
2497
2498 CONVERT_DOUBLE_CHECKED(x, args[0]);
2499 return Heap::NumberFromDouble(floor(x));
2500}
2501
2502
2503static Object* Runtime_Math_log(Arguments args) {
2504 NoHandleAllocation ha;
2505 ASSERT(args.length() == 1);
2506
2507 CONVERT_DOUBLE_CHECKED(x, args[0]);
2508 return Heap::AllocateHeapNumber(log(x));
2509}
2510
2511
2512static Object* Runtime_Math_pow(Arguments args) {
2513 NoHandleAllocation ha;
2514 ASSERT(args.length() == 2);
2515
2516 CONVERT_DOUBLE_CHECKED(x, args[0]);
2517 CONVERT_DOUBLE_CHECKED(y, args[1]);
2518 if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
2519 return Heap::nan_value();
2520 } else if (y == 0) {
2521 return Smi::FromInt(1);
2522 } else {
2523 return Heap::AllocateHeapNumber(pow(x, y));
2524 }
2525}
2526
2527// Returns a number value with positive sign, greater than or equal to
2528// 0 but less than 1, chosen randomly.
2529static Object* Runtime_Math_random(Arguments) {
2530 NoHandleAllocation ha;
2531
2532 // To get much better precision, we combine the results of two
2533 // invocations of random(). The result is computed by normalizing a
2534 // double in the range [0, RAND_MAX + 1) obtained by adding the
2535 // high-order bits in the range [0, RAND_MAX] with the low-order
2536 // bits in the range [0, 1).
2537 double lo = static_cast<double>(random()) / (RAND_MAX + 1.0);
2538 double hi = static_cast<double>(random());
2539 double result = (hi + lo) / (RAND_MAX + 1.0);
2540 ASSERT(result >= 0 && result < 1);
2541 return Heap::AllocateHeapNumber(result);
2542}
2543
2544
2545static Object* Runtime_Math_round(Arguments args) {
2546 NoHandleAllocation ha;
2547 ASSERT(args.length() == 1);
2548
2549 CONVERT_DOUBLE_CHECKED(x, args[0]);
2550 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
2551 return Heap::NumberFromDouble(floor(x + 0.5));
2552}
2553
2554
2555static Object* Runtime_Math_sin(Arguments args) {
2556 NoHandleAllocation ha;
2557 ASSERT(args.length() == 1);
2558
2559 CONVERT_DOUBLE_CHECKED(x, args[0]);
2560 return Heap::AllocateHeapNumber(sin(x));
2561}
2562
2563
2564static Object* Runtime_Math_sqrt(Arguments args) {
2565 NoHandleAllocation ha;
2566 ASSERT(args.length() == 1);
2567
2568 CONVERT_DOUBLE_CHECKED(x, args[0]);
2569 return Heap::AllocateHeapNumber(sqrt(x));
2570}
2571
2572
2573static Object* Runtime_Math_tan(Arguments args) {
2574 NoHandleAllocation ha;
2575 ASSERT(args.length() == 1);
2576
2577 CONVERT_DOUBLE_CHECKED(x, args[0]);
2578 return Heap::AllocateHeapNumber(tan(x));
2579}
2580
2581
2582static Object* Runtime_NewArguments(Arguments args) {
2583 NoHandleAllocation ha;
2584 ASSERT(args.length() == 1);
2585
2586 // ECMA-262, 3rd., 10.1.8, p.39
2587 CONVERT_CHECKED(JSFunction, callee, args[0]);
2588
2589 // Compute the frame holding the arguments.
2590 JavaScriptFrameIterator it;
2591 it.AdvanceToArgumentsFrame();
2592 JavaScriptFrame* frame = it.frame();
2593
2594 const int length = frame->GetProvidedParametersCount();
2595 Object* result = Heap::AllocateArgumentsObject(callee, length);
2596 if (result->IsFailure()) return result;
2597 FixedArray* array = FixedArray::cast(JSObject::cast(result)->elements());
2598 ASSERT(array->length() == length);
2599 for (int i = 0; i < length; i++) {
2600 array->set(i, frame->GetParameter(i));
2601 }
2602 return result;
2603}
2604
2605
2606static Object* Runtime_NewClosure(Arguments args) {
2607 HandleScope scope;
2608 ASSERT(args.length() == 2);
2609 CONVERT_ARG_CHECKED(JSFunction, boilerplate, 0);
2610 CONVERT_ARG_CHECKED(Context, context, 1);
2611
2612 Handle<JSFunction> result =
2613 Factory::NewFunctionFromBoilerplate(boilerplate, context);
2614 return *result;
2615}
2616
2617
2618static Object* Runtime_NewObject(Arguments args) {
2619 NoHandleAllocation ha;
2620 ASSERT(args.length() == 1);
2621
2622 Object* constructor = args[0];
2623 if (constructor->IsJSFunction()) {
2624 JSFunction* function = JSFunction::cast(constructor);
2625
2626 // Handle steping into constructors.
2627 if (Debug::StepInActive()) {
2628 StackFrameIterator it;
2629 it.Advance();
2630 ASSERT(InternalFrame::cast(it.frame())->is_construct_trampoline());
2631 it.Advance();
2632 if (it.frame()->fp() == Debug::step_in_fp()) {
2633 HandleScope scope;
2634 Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
2635 }
2636 }
2637
2638 if (function->has_initial_map() &&
2639 function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
2640 // The 'Function' function ignores the receiver object when
2641 // called using 'new' and creates a new JSFunction object that
2642 // is returned. The receiver object is only used for error
2643 // reporting if an error occurs when constructing the new
2644 // JSFunction. AllocateJSObject should not be used to allocate
2645 // JSFunctions since it does not properly initialize the shared
2646 // part of the function. Since the receiver is ignored anyway,
2647 // we use the global object as the receiver instead of a new
2648 // JSFunction object. This way, errors are reported the same
2649 // way whether or not 'Function' is called using 'new'.
2650 return Top::context()->global();
2651 }
2652 return Heap::AllocateJSObject(function);
2653 }
2654
2655 HandleScope scope;
2656 Handle<Object> cons(constructor);
2657 // The constructor is not a function; throw a type error.
2658 Handle<Object> type_error =
2659 Factory::NewTypeError("not_constructor", HandleVector(&cons, 1));
2660 return Top::Throw(*type_error);
2661}
2662
2663
2664#ifdef DEBUG
2665DEFINE_bool(trace_lazy, false, "trace lazy compilation");
2666#endif
2667
2668
2669static Object* Runtime_LazyCompile(Arguments args) {
2670 HandleScope scope;
2671 ASSERT(args.length() == 1);
2672
2673 Handle<JSFunction> function = args.at<JSFunction>(0);
2674#ifdef DEBUG
2675 if (FLAG_trace_lazy) {
2676 PrintF("[lazy: ");
2677 function->shared()->name()->Print();
2678 PrintF("]\n");
2679 }
2680#endif
2681
2682 // Compile the target function.
2683 ASSERT(!function->is_compiled());
2684 if (!CompileLazy(function, KEEP_EXCEPTION)) {
2685 return Failure::Exception();
2686 }
2687
2688 return function->code();
2689}
2690
2691
2692static Object* Runtime_GetCalledFunction(Arguments args) {
2693 HandleScope scope;
2694 ASSERT(args.length() == 1);
2695 StackFrameIterator it;
2696 // Get past the JS-to-C exit frame.
2697 ASSERT(it.frame()->is_exit());
2698 it.Advance();
2699 // Get past the CALL_NON_FUNCTION activation frame.
2700 ASSERT(it.frame()->is_java_script());
2701 it.Advance();
2702 // Argument adaptor frames do not copy the function; we have to skip
2703 // past them to get to the real calling frame.
2704 if (it.frame()->is_arguments_adaptor()) it.Advance();
2705 // Get the function from the top of the expression stack of the
2706 // calling frame.
2707 StandardFrame* frame = StandardFrame::cast(it.frame());
2708 int index = frame->ComputeExpressionsCount() - 1;
2709 Object* result = frame->GetExpression(index);
2710 return result;
2711}
2712
2713
2714static Object* Runtime_GetFunctionDelegate(Arguments args) {
2715 HandleScope scope;
2716 ASSERT(args.length() == 1);
2717 RUNTIME_ASSERT(!args[0]->IsJSFunction());
2718 return *Execution::GetFunctionDelegate(args.at<Object>(0));
2719}
2720
2721
2722static Object* Runtime_NewContext(Arguments args) {
2723 NoHandleAllocation ha;
2724 ASSERT(args.length() == 2);
2725
2726 CONVERT_CHECKED(JSFunction, function, args[1]);
2727 int length = ScopeInfo<>::NumberOfContextSlots(function->code());
2728 Object* result = Heap::AllocateFunctionContext(length, function);
2729 if (result->IsFailure()) return result;
2730
2731 Top::set_context(Context::cast(result));
2732
2733 return args[0]; // return TOS
2734}
2735
2736
2737static Object* Runtime_PushContext(Arguments args) {
2738 NoHandleAllocation ha;
2739 ASSERT(args.length() == 2);
2740
2741 // Convert the object to a proper JavaScript object.
2742 Object* object = args[1];
2743 if (!object->IsJSObject()) {
2744 object = object->ToObject();
2745 if (object->IsFailure()) {
2746 if (!Failure::cast(object)->IsInternalError()) return object;
2747 HandleScope scope;
2748 Handle<Object> handle(args[1]);
2749 Handle<Object> result =
2750 Factory::NewTypeError("with_expression", HandleVector(&handle, 1));
2751 return Top::Throw(*result);
2752 }
2753 }
2754
2755 Object* result =
2756 Heap::AllocateWithContext(Top::context(), JSObject::cast(object));
2757 if (result->IsFailure()) return result;
2758
2759 Top::set_context(Context::cast(result));
2760
2761 return args[0]; // return TOS
2762}
2763
2764
2765static Object* Runtime_LookupContext(Arguments args) {
2766 HandleScope scope;
2767 ASSERT(args.length() == 2);
2768
2769 CONVERT_ARG_CHECKED(Context, context, 0);
2770 CONVERT_ARG_CHECKED(String, name, 1);
2771
2772 int index;
2773 PropertyAttributes attributes;
2774 ContextLookupFlags flags = FOLLOW_CHAINS;
2775 Handle<Object> context_obj =
2776 context->Lookup(name, flags, &index, &attributes);
2777
2778 if (index < 0 && *context_obj != NULL) {
2779 ASSERT(context_obj->IsJSObject());
2780 return *context_obj;
2781 }
2782
2783 // No intermediate context found. Use global object by default.
2784 return Top::context()->global();
2785}
2786
2787
2788
2789
2790// A mechanism to return pairs of Object*'s. This is somewhat
2791// compiler-dependent as it assumes that a 64-bit value (a long long)
2792// is returned via two registers (edx:eax on ia32). Both the ia32 and
2793// arm platform support this; it is mostly an issue of "coaxing" the
2794// compiler to do the right thing.
2795//
2796// TODO(1236026): This is a non-portable hack that should be removed.
2797typedef uint64_t ObjPair;
2798ObjPair MakePair(Object* x, Object* y) {
2799 return reinterpret_cast<uint32_t>(x) |
2800 (reinterpret_cast<ObjPair>(y) << 32);
2801}
2802
2803
2804static Object* Unhole(Object* x, PropertyAttributes attributes) {
2805 ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
2806 USE(attributes);
2807 return x->IsTheHole() ? Heap::undefined_value() : x;
2808}
2809
2810
2811static ObjPair LoadContextSlotHelper(Arguments args, bool throw_error) {
2812 HandleScope scope;
2813 ASSERT(args.length() == 2);
2814
2815 if (!args[0]->IsContext()) return MakePair(IllegalOperation(), NULL);
2816 Handle<Context> context = args.at<Context>(0);
2817 Handle<String> name(String::cast(args[1]));
2818
2819 int index;
2820 PropertyAttributes attributes;
2821 ContextLookupFlags flags = FOLLOW_CHAINS;
2822 Handle<Object> context_obj =
2823 context->Lookup(name, flags, &index, &attributes);
2824
2825 if (index >= 0) {
2826 if (context_obj->IsContext()) {
2827 // The context is an Execution context, and the "property" we were looking
2828 // for is a local variable in that context. According to ECMA-262, 3rd.,
2829 // 10.1.6 and 10.2.3, the receiver is the global object.
2830 return MakePair(
2831 Unhole(Handle<Context>::cast(context_obj)->get(index), attributes),
2832 Top::context()->global());
2833 } else {
2834 return MakePair(
2835 Unhole(Handle<JSObject>::cast(context_obj)->GetElement(index),
2836 attributes),
2837 *context_obj);
2838 }
2839 }
2840
2841 if (*context_obj != NULL) {
2842 ASSERT(Handle<JSObject>::cast(context_obj)->HasProperty(*name));
2843 // Note: As of 5/29/2008, GetProperty does the "unholing" and so this call
2844 // here is redundant. We left it anyway, to be explicit; also it's not clear
2845 // why GetProperty should do the unholing in the first place.
2846 return MakePair(
2847 Unhole(Handle<JSObject>::cast(context_obj)->GetProperty(*name),
2848 attributes),
2849 *context_obj);
2850 }
2851
2852 if (throw_error) {
2853 // The property doesn't exist - throw exception.
2854 Handle<Object> reference_error =
2855 Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
2856 return MakePair(Top::Throw(*reference_error), NULL);
2857 } else {
2858 // The property doesn't exist - return undefined
2859 return MakePair(Heap::undefined_value(), Heap::undefined_value());
2860 }
2861}
2862
2863
2864static ObjPair Runtime_LoadContextSlot(Arguments args) {
2865 return LoadContextSlotHelper(args, true);
2866}
2867
2868
2869static ObjPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
2870 return LoadContextSlotHelper(args, false);
2871}
2872
2873
2874static Object* Runtime_StoreContextSlot(Arguments args) {
2875 HandleScope scope;
2876 ASSERT(args.length() == 3);
2877
2878 Handle<Object> value(args[0]);
2879 CONVERT_ARG_CHECKED(Context, context, 1);
2880 Handle<String> name(String::cast(args[2]));
2881
2882 int index;
2883 PropertyAttributes attributes;
2884 ContextLookupFlags flags = FOLLOW_CHAINS;
2885 Handle<Object> context_obj =
2886 context->Lookup(name, flags, &index, &attributes);
2887
2888 if (index >= 0) {
2889 if (context_obj->IsContext()) {
2890 // Ignore if read_only variable.
2891 if ((attributes & READ_ONLY) == 0) {
2892 Handle<Context>::cast(context_obj)->set(index, *value);
2893 }
2894 } else {
2895 ASSERT((attributes & READ_ONLY) == 0);
2896 Object* result =
2897 Handle<JSObject>::cast(context_obj)->SetElement(index, *value);
2898 USE(result);
2899 ASSERT(!result->IsFailure());
2900 }
2901 return *value;
2902 }
2903
2904 // Slow case: The property is not in a FixedArray context.
2905 // It is either in an JSObject extension context or it was not found.
2906 Handle<JSObject> context_ext;
2907
2908 if (*context_obj != NULL) {
2909 // The property exists in the extension context.
2910 context_ext = Handle<JSObject>::cast(context_obj);
2911 } else {
2912 // The property was not found. It needs to be stored in the global context.
2913 ASSERT(attributes == ABSENT);
2914 attributes = NONE;
2915 context_ext = Handle<JSObject>(Top::context()->global());
2916 }
2917
2918 // Set the property, but ignore if read_only variable.
2919 if ((attributes & READ_ONLY) == 0) {
2920 Handle<Object> set = SetProperty(context_ext, name, value, attributes);
2921 if (set.is_null()) {
2922 // Failure::Exception is converted to a null handle in the
2923 // handle-based methods such as SetProperty. We therefore need
2924 // to convert null handles back to exceptions.
2925 ASSERT(Top::has_pending_exception());
2926 return Failure::Exception();
2927 }
2928 }
2929 return *value;
2930}
2931
2932
2933static Object* Runtime_Throw(Arguments args) {
2934 HandleScope scope;
2935 ASSERT(args.length() == 1);
2936
2937 return Top::Throw(args[0]);
2938}
2939
2940
2941static Object* Runtime_ReThrow(Arguments args) {
2942 HandleScope scope;
2943 ASSERT(args.length() == 1);
2944
2945 return Top::ReThrow(args[0]);
2946}
2947
2948
2949static Object* Runtime_ThrowReferenceError(Arguments args) {
2950 HandleScope scope;
2951 ASSERT(args.length() == 1);
2952
2953 Handle<Object> name(args[0]);
2954 Handle<Object> reference_error =
2955 Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
2956 return Top::Throw(*reference_error);
2957}
2958
2959
2960static Object* Runtime_StackOverflow(Arguments args) {
2961 NoHandleAllocation na;
2962 return Top::StackOverflow();
2963}
2964
2965
2966static Object* RuntimePreempt(Arguments args) {
2967 // Clear the preempt request flag.
2968 StackGuard::Continue(PREEMPT);
2969
2970 ContextSwitcher::PreemptionReceived();
2971
2972 {
2973 v8::Unlocker unlocker;
2974 Thread::YieldCPU();
2975 }
2976
2977 return Heap::undefined_value();
2978}
2979
2980
2981static Object* Runtime_DebugBreak(Arguments args) {
2982 // Don't break in system functions. If the current function is either in the
2983 // builtins object of some context or is in the debug context just return with
2984 // the debug break stack guard active.
2985 JavaScriptFrameIterator it;
2986 JavaScriptFrame* frame = it.frame();
2987 Object* fun = frame->function();
2988 if (fun->IsJSFunction()) {
2989 GlobalObject* global = JSFunction::cast(fun)->context()->global();
2990 if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
2991 return args[0];
2992 }
2993 }
2994
2995 // Clear the debug request flag.
2996 StackGuard::Continue(DEBUGBREAK);
2997
2998 // Make sure debugger is loaded.
2999 if (!Debug::Load()) {
3000 return args[0];
3001 }
3002
3003 HandleScope scope;
3004 SaveBreakFrame save;
3005 EnterDebuggerContext enter;
3006
3007 // Process debug requests. Returns true if break request.
3008 bool break_request = Debugger::ProcessPendingRequests();
3009
3010 // Notify the debug event listeners if break request.
3011 if (break_request) {
3012 Debugger::OnDebugBreak(Factory::undefined_value());
3013 }
3014
3015 // Return to continue execution.
3016 return args[0];
3017}
3018
3019
3020static Object* Runtime_StackGuard(Arguments args) {
3021 ASSERT(args.length() == 1);
3022
3023 // First check if this is a real stack overflow.
3024 if (StackGuard::IsStackOverflow()) return Runtime_StackOverflow(args);
3025
3026 // If not real stack overflow the stack guard was used to interrupt
3027 // execution for another purpose.
3028 if (StackGuard::IsDebugBreak()) Runtime_DebugBreak(args);
3029 if (StackGuard::IsPreempted()) RuntimePreempt(args);
3030 if (StackGuard::IsInterrupted()) {
3031 // interrupt
3032 StackGuard::Continue(INTERRUPT);
3033 return Top::StackOverflow();
3034 }
3035 return Heap::undefined_value();
3036}
3037
3038
3039// NOTE: These PrintXXX functions are defined for all builds (not just
3040// DEBUG builds) because we may want to be able to trace function
3041// calls in all modes.
3042static void PrintString(String* str) {
3043 // not uncommon to have empty strings
3044 if (str->length() > 0) {
3045 SmartPointer<char> s =
3046 str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
3047 PrintF("%s", *s);
3048 }
3049}
3050
3051
3052static void PrintObject(Object* obj) {
3053 if (obj->IsSmi()) {
3054 PrintF("%d", Smi::cast(obj)->value());
3055 } else if (obj->IsString() || obj->IsSymbol()) {
3056 PrintString(String::cast(obj));
3057 } else if (obj->IsNumber()) {
3058 PrintF("%g", obj->Number());
3059 } else if (obj->IsFailure()) {
3060 PrintF("<failure>");
3061 } else if (obj->IsUndefined()) {
3062 PrintF("<undefined>");
3063 } else if (obj->IsNull()) {
3064 PrintF("<null>");
3065 } else if (obj->IsTrue()) {
3066 PrintF("<true>");
3067 } else if (obj->IsFalse()) {
3068 PrintF("<false>");
3069 } else {
3070 PrintF("%p", obj);
3071 }
3072}
3073
3074
3075static int StackSize() {
3076 int n = 0;
3077 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
3078 return n;
3079}
3080
3081
3082static void PrintTransition(Object* result) {
3083 // indentation
3084 { const int nmax = 80;
3085 int n = StackSize();
3086 if (n <= nmax)
3087 PrintF("%4d:%*s", n, n, "");
3088 else
3089 PrintF("%4d:%*s", n, nmax, "...");
3090 }
3091
3092 if (result == NULL) {
3093 // constructor calls
3094 JavaScriptFrameIterator it;
3095 JavaScriptFrame* frame = it.frame();
3096 if (frame->IsConstructor()) PrintF("new ");
3097 // function name
3098 Object* fun = frame->function();
3099 if (fun->IsJSFunction()) {
3100 PrintObject(JSFunction::cast(fun)->shared()->name());
3101 } else {
3102 PrintObject(fun);
3103 }
3104 // function arguments
3105 // (we are intentionally only printing the actually
3106 // supplied parameters, not all parameters required)
3107 PrintF("(this=");
3108 PrintObject(frame->receiver());
3109 const int length = frame->GetProvidedParametersCount();
3110 for (int i = 0; i < length; i++) {
3111 PrintF(", ");
3112 PrintObject(frame->GetParameter(i));
3113 }
3114 PrintF(") {\n");
3115
3116 } else {
3117 // function result
3118 PrintF("} -> ");
3119 PrintObject(result);
3120 PrintF("\n");
3121 }
3122}
3123
3124
3125static Object* Runtime_TraceEnter(Arguments args) {
3126 NoHandleAllocation ha;
3127 PrintTransition(NULL);
3128 return args[0]; // return TOS
3129}
3130
3131
3132static Object* Runtime_TraceExit(Arguments args) {
3133 NoHandleAllocation ha;
3134 PrintTransition(args[0]);
3135 return args[0]; // return TOS
3136}
3137
3138
3139static Object* Runtime_DebugPrint(Arguments args) {
3140 NoHandleAllocation ha;
3141 ASSERT(args.length() == 1);
3142
3143#ifdef DEBUG
3144 if (args[0]->IsString()) {
3145 // If we have a string, assume it's a code "marker"
3146 // and print some interesting cpu debugging info.
3147 JavaScriptFrameIterator it;
3148 JavaScriptFrame* frame = it.frame();
3149 PrintF("fp = %p, sp = %p, pp = %p: ",
3150 frame->fp(), frame->sp(), frame->pp());
3151 } else {
3152 PrintF("DebugPrint: ");
3153 }
3154 args[0]->Print();
3155#else
3156 PrintF("DebugPrint: %p", args[0]);
3157#endif
3158 PrintF("\n");
3159
3160 return args[0]; // return TOS
3161}
3162
3163
3164static Object* Runtime_DebugTrace(Arguments args) {
3165 ASSERT(args.length() == 1);
3166 NoHandleAllocation ha;
3167 Top::PrintStack();
3168 return args[0]; // return TOS
3169}
3170
3171
3172static Object* Runtime_DateCurrentTime(Arguments) {
3173 NoHandleAllocation ha;
3174
3175 // According to ECMA-262, section 15.9.1, page 117, the precision of
3176 // the number in a Date object representing a particular instant in
3177 // time is milliseconds. Therefore, we floor the result of getting
3178 // the OS time.
3179 double millis = floor(OS::TimeCurrentMillis());
3180 return Heap::NumberFromDouble(millis);
3181}
3182
3183
3184static Object* Runtime_DateParseString(Arguments args) {
3185 HandleScope scope;
3186 ASSERT(args.length() == 1);
3187
3188 CONVERT_CHECKED(String, string_object, args[0]);
3189
3190 Handle<String> str(string_object);
3191 Handle<FixedArray> output = Factory::NewFixedArray(DateParser::OUTPUT_SIZE);
3192 if (DateParser::Parse(*str, *output)) {
3193 return *Factory::NewJSArrayWithElements(output);
3194 } else {
3195 return *Factory::null_value();
3196 }
3197}
3198
3199
3200static Object* Runtime_DateLocalTimezone(Arguments args) {
3201 NoHandleAllocation ha;
3202 ASSERT(args.length() == 1);
3203
3204 CONVERT_DOUBLE_CHECKED(x, args[0]);
3205 char* zone = OS::LocalTimezone(x);
3206 return Heap::AllocateStringFromUtf8(CStrVector(zone));
3207}
3208
3209
3210static Object* Runtime_DateLocalTimeOffset(Arguments args) {
3211 NoHandleAllocation ha;
3212 ASSERT(args.length() == 1);
3213
3214 return Heap::NumberFromDouble(OS::LocalTimeOffset());
3215}
3216
3217
3218static Object* Runtime_DateDaylightSavingsOffset(Arguments args) {
3219 NoHandleAllocation ha;
3220 ASSERT(args.length() == 1);
3221
3222 CONVERT_DOUBLE_CHECKED(x, args[0]);
3223 return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x));
3224}
3225
3226
3227
3228static Object* Runtime_NumberIsNaN(Arguments args) {
3229 NoHandleAllocation ha;
3230 ASSERT(args.length() == 1);
3231
3232 CONVERT_DOUBLE_CHECKED(value, args[0]);
3233 if (isnan(value)) {
3234 return Heap::true_value();
3235 } else {
3236 return Heap::false_value();
3237 }
3238}
3239
3240
3241static Object* Runtime_NumberIsFinite(Arguments args) {
3242 NoHandleAllocation ha;
3243 ASSERT(args.length() == 1);
3244
3245 CONVERT_DOUBLE_CHECKED(value, args[0]);
3246 Object* result;
3247 if (isnan(value) || (fpclassify(value) == FP_INFINITE)) {
3248 result = Heap::false_value();
3249 } else {
3250 result = Heap::true_value();
3251 }
3252 return result;
3253}
3254
3255
3256static Object* Runtime_NumberMaxValue(Arguments) {
3257 NoHandleAllocation ha;
3258
3259 return Heap::number_max_value();
3260}
3261
3262
3263static Object* Runtime_NumberMinValue(Arguments) {
3264 NoHandleAllocation ha;
3265
3266 return Heap::number_min_value();
3267}
3268
3269
3270static Object* Runtime_NumberNaN(Arguments) {
3271 NoHandleAllocation ha;
3272
3273 return Heap::nan_value();
3274}
3275
3276
3277static Object* Runtime_NumberNegativeInfinity(Arguments) {
3278 NoHandleAllocation ha;
3279
3280 return Heap::negative_infinity_value();
3281}
3282
3283
3284static Object* Runtime_NumberPositiveInfinity(Arguments) {
3285 NoHandleAllocation ha;
3286
3287 return Heap::infinity_value();
3288}
3289
3290
3291static Object* EvalContext() {
3292 // The topmost JS frame belongs to the eval function which called
3293 // the CompileString runtime function. We need to unwind one level
3294 // to get to the caller of eval.
3295 StackFrameLocator locator;
3296 JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
3297
3298 // Check if the caller of eval() supports eval. If not, eval is
3299 // called through an alias in which case we throw an EvalError.
3300 HandleScope scope;
3301 if (!ScopeInfo<>::SupportsEval(frame->FindCode())) {
3302 Handle<Object> error =
3303 Factory::NewEvalError("illegal_eval", HandleVector<Object>(NULL, 0));
3304 return Top::Throw(*error);
3305 }
3306
3307 // Fetch the caller context from the frame.
3308 Handle<Context> caller(Context::cast(frame->context()));
3309
3310 // Check for eval() invocations that cross environments. Use the
3311 // context from the stack if evaluating in current environment.
3312 Handle<Context> target = Top::global_context();
3313 if (caller->global_context() == *target) return *caller;
3314
3315 // Compute a function closure that captures the calling context. We
3316 // need a function that has trivial scope info, since it is only
3317 // used to hold the context chain together.
3318 Handle<JSFunction> closure = Factory::NewFunction(Factory::empty_symbol(),
3319 Factory::undefined_value());
3320 closure->set_context(*caller);
3321
3322 // Create a new adaptor context that has the target environment as
3323 // the extension object. This enables the evaluated code to see both
3324 // the current context with locals and everything and to see global
3325 // variables declared in the target global object. Furthermore, any
3326 // properties introduced with 'var' will be added to the target
3327 // global object because it is the extension object.
3328 Handle<Context> adaptor =
3329 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, closure);
3330 adaptor->set_extension(target->global());
3331 return *adaptor;
3332}
3333
3334
3335static Object* Runtime_EvalReceiver(Arguments args) {
3336 StackFrameLocator locator;
3337 return locator.FindJavaScriptFrame(1)->receiver();
3338}
3339
3340
3341static Object* Runtime_CompileString(Arguments args) {
3342 HandleScope scope;
3343 ASSERT(args.length() == 2);
3344 bool contextual = args[1]->IsTrue();
3345 RUNTIME_ASSERT(contextual || args[1]->IsFalse());
3346
3347 // Compute the eval context.
3348 Handle<Context> context;
3349 if (contextual) {
3350 // Get eval context. May not be available if we are calling eval
3351 // through an alias, and the corresponding frame doesn't have a
3352 // proper eval context set up.
3353 Object* eval_context = EvalContext();
3354 if (eval_context->IsFailure()) return eval_context;
3355 context = Handle<Context>(Context::cast(eval_context));
3356 } else {
3357 context = Handle<Context>(Top::context()->global_context());
3358 }
3359
3360 // Compile eval() source.
3361 Handle<String> source(String::cast(args[0]));
3362 Handle<JSFunction> boilerplate =
3363 Compiler::CompileEval(context->IsGlobalContext(), source);
3364 if (boilerplate.is_null()) return Failure::Exception();
3365 Handle<JSFunction> fun =
3366 Factory::NewFunctionFromBoilerplate(boilerplate, context);
3367 return *fun;
3368}
3369
3370
3371static Object* Runtime_CompileScript(Arguments args) {
3372 HandleScope scope;
3373 ASSERT(args.length() == 4);
3374
3375 CONVERT_ARG_CHECKED(String, source, 0);
3376 CONVERT_ARG_CHECKED(String, script, 1);
3377 CONVERT_CHECKED(Smi, line_attrs, args[2]);
3378 int line = line_attrs->value();
3379 CONVERT_CHECKED(Smi, col_attrs, args[3]);
3380 int col = col_attrs->value();
3381 Handle<JSFunction> boilerplate =
3382 Compiler::Compile(source, script, line, col, NULL, NULL);
3383 if (boilerplate.is_null()) return Failure::Exception();
3384 Handle<JSFunction> fun =
3385 Factory::NewFunctionFromBoilerplate(boilerplate,
3386 Handle<Context>(Top::context()));
3387 return *fun;
3388}
3389
3390
3391static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
3392 // This utility adjusts the property attributes for newly created Function
3393 // object ("new Function(...)") by changing the map.
3394 // All it does is changing the prototype property to enumerable
3395 // as specified in ECMA262, 15.3.5.2.
3396 HandleScope scope;
3397 ASSERT(args.length() == 1);
3398 CONVERT_ARG_CHECKED(JSFunction, func, 0);
3399 ASSERT(func->map()->instance_type() ==
3400 Top::function_instance_map()->instance_type());
3401 ASSERT(func->map()->instance_size() ==
3402 Top::function_instance_map()->instance_size());
3403 func->set_map(*Top::function_instance_map());
3404 return *func;
3405}
3406
3407
3408// This will not allocate (flatten the string), but it may run
3409// very slowly for very deeply nested ConsStrings. For debugging use only.
3410static Object* Runtime_GlobalPrint(Arguments args) {
3411 NoHandleAllocation ha;
3412 ASSERT(args.length() == 1);
3413
3414 CONVERT_CHECKED(String, string, args[0]);
3415 StringInputBuffer buffer(string);
3416 while (buffer.has_more()) {
3417 uint16_t character = buffer.GetNext();
3418 PrintF("%c", character);
3419 }
3420 return string;
3421}
3422
3423
3424static Object* Runtime_RemoveArrayHoles(Arguments args) {
3425 ASSERT(args.length() == 1);
3426 // Ignore the case if this is not a JSArray.
3427 if (!args[0]->IsJSArray()) return args[0];
3428 return JSArray::cast(args[0])->RemoveHoles();
3429}
3430
3431
3432// Move contents of argument 0 (an array) to argument 1 (an array)
3433static Object* Runtime_MoveArrayContents(Arguments args) {
3434 ASSERT(args.length() == 2);
3435 CONVERT_CHECKED(JSArray, from, args[0]);
3436 CONVERT_CHECKED(JSArray, to, args[1]);
3437 to->SetContent(FixedArray::cast(from->elements()));
3438 to->set_length(from->length());
3439 from->SetContent(Heap::empty_fixed_array());
3440 from->set_length(0);
3441 return to;
3442}
3443
3444
3445// How many elements does this array have?
3446static Object* Runtime_EstimateNumberOfElements(Arguments args) {
3447 ASSERT(args.length() == 1);
3448 CONVERT_CHECKED(JSArray, array, args[0]);
3449 HeapObject* elements = array->elements();
3450 if (elements->IsDictionary()) {
3451 return Smi::FromInt(Dictionary::cast(elements)->NumberOfElements());
3452 } else {
3453 return array->length();
3454 }
3455}
3456
3457
3458// Returns an array that tells you where in the [0, length) interval an array
3459// might have elements. Can either return keys or intervals. Keys can have
3460// gaps in (undefined). Intervals can also span over some undefined keys.
3461static Object* Runtime_GetArrayKeys(Arguments args) {
3462 ASSERT(args.length() == 2);
3463 HandleScope scope;
3464 CONVERT_CHECKED(JSArray, raw_array, args[0]);
3465 Handle<JSArray> array(raw_array);
3466 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
3467 HeapObject* elements = array->elements();
3468 if (elements->IsDictionary()) {
3469 // Create an array and get all the keys into it, then remove all the
3470 // keys that are not integers in the range 0 to length-1.
3471 Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
3472 int keys_length = keys->length();
3473 for (int i = 0; i < keys_length; i++) {
3474 Object* key = keys->get(i);
3475 uint32_t index;
3476 if (!Array::IndexFromObject(key, &index) || index >= length) {
3477 // Zap invalid keys.
3478 keys->set_undefined(i);
3479 }
3480 }
3481 return *Factory::NewJSArrayWithElements(keys);
3482 } else {
3483 Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
3484 // -1 means start of array.
3485 single_interval->set(0, Smi::FromInt(-1));
3486 Handle<Object> length_object =
3487 Factory::NewNumber(static_cast<double>(length));
3488 single_interval->set(1, *length_object);
3489 return *Factory::NewJSArrayWithElements(single_interval);
3490 }
3491}
3492
3493
3494// DefineAccessor takes an optional final argument which is the
3495// property attributes (eg, DONT_ENUM, DONT_DELETE). IMPORTANT: due
3496// to the way accessors are implemented, it is set for both the getter
3497// and setter on the first call to DefineAccessor and ignored on
3498// subsequent calls.
3499static Object* Runtime_DefineAccessor(Arguments args) {
3500 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
3501 // Compute attributes.
3502 PropertyAttributes attributes = NONE;
3503 if (args.length() == 5) {
3504 CONVERT_CHECKED(Smi, attrs, args[4]);
3505 int value = attrs->value();
3506 // Only attribute bits should be set.
3507 ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3508 attributes = static_cast<PropertyAttributes>(value);
3509 }
3510
3511 CONVERT_CHECKED(JSObject, obj, args[0]);
3512 CONVERT_CHECKED(String, name, args[1]);
3513 CONVERT_CHECKED(Smi, flag, args[2]);
3514 CONVERT_CHECKED(JSFunction, fun, args[3]);
3515 return obj->DefineAccessor(name, flag->value() == 0, fun, attributes);
3516}
3517
3518
3519static Object* Runtime_LookupAccessor(Arguments args) {
3520 ASSERT(args.length() == 3);
3521 CONVERT_CHECKED(JSObject, obj, args[0]);
3522 CONVERT_CHECKED(String, name, args[1]);
3523 CONVERT_CHECKED(Smi, flag, args[2]);
3524 return obj->LookupAccessor(name, flag->value() == 0);
3525}
3526
3527
3528// Helper functions for wrapping and unwrapping stack frame ids.
3529static Smi* WrapFrameId(StackFrame::Id id) {
3530 ASSERT(IsAligned(OffsetFrom(id), 4));
3531 return Smi::FromInt(id >> 2);
3532}
3533
3534
3535static StackFrame::Id UnwrapFrameId(Smi* wrapped) {
3536 return static_cast<StackFrame::Id>(wrapped->value() << 2);
3537}
3538
3539
3540// Adds a JavaScript function as a debug event listener.
3541// args[0]: debug event listener function
3542// args[1]: object supplied during callback
3543static Object* Runtime_AddDebugEventListener(Arguments args) {
3544 ASSERT(args.length() == 2);
3545 // Convert the parameters to API objects to call the API function for adding
3546 // a JavaScript function as debug event listener.
3547 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
3548 v8::Handle<v8::Function> fun(ToApi<v8::Function>(raw_fun));
3549 v8::Handle<v8::Value> data(ToApi<v8::Value>(args.at<Object>(0)));
3550 v8::Debug::AddDebugEventListener(fun, data);
3551
3552 return Heap::undefined_value();
3553}
3554
3555
3556// Removes a JavaScript function debug event listener.
3557// args[0]: debug event listener function
3558static Object* Runtime_RemoveDebugEventListener(Arguments args) {
3559 ASSERT(args.length() == 1);
3560 // Convert the parameter to an API object to call the API function for
3561 // removing a JavaScript function debug event listener.
3562 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
3563 v8::Handle<v8::Function> fun(ToApi<v8::Function>(raw_fun));
3564 v8::Debug::RemoveDebugEventListener(fun);
3565
3566 return Heap::undefined_value();
3567}
3568
3569
3570static Object* Runtime_Break(Arguments args) {
3571 ASSERT(args.length() == 1);
3572 StackGuard::DebugBreak();
3573 return Heap::undefined_value();
3574}
3575
3576
3577static Object* DebugLookupResultValue(LookupResult* result) {
3578 Object* value;
3579 switch (result->type()) {
3580 case NORMAL: {
3581 Dictionary* dict =
3582 JSObject::cast(result->holder())->property_dictionary();
3583 value = dict->ValueAt(result->GetDictionaryEntry());
3584 if (value->IsTheHole()) {
3585 return Heap::undefined_value();
3586 }
3587 return value;
3588 }
3589 case FIELD:
3590 value =
3591 JSObject::cast(
3592 result->holder())->properties()->get(result->GetFieldIndex());
3593 if (value->IsTheHole()) {
3594 return Heap::undefined_value();
3595 }
3596 return value;
3597 case CONSTANT_FUNCTION:
3598 return result->GetConstantFunction();
3599 case CALLBACKS:
3600 return Heap::undefined_value();
3601 case MAP_TRANSITION:
3602 return Heap::undefined_value();
3603 case INTERCEPTOR:
3604 return Heap::undefined_value();
3605 default:
3606 UNREACHABLE();
3607 }
3608 return Heap::undefined_value();
3609}
3610
3611
3612static Object* Runtime_DebugGetLocalPropertyDetails(Arguments args) {
3613 HandleScope scope;
3614
3615 ASSERT(args.length() == 2);
3616
3617 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3618 CONVERT_ARG_CHECKED(String, name, 1);
3619
3620 // Check if the name is trivially convertible to an index and get the element
3621 // if so.
3622 uint32_t index;
3623 if (name->AsArrayIndex(&index)) {
3624 Handle<FixedArray> details = Factory::NewFixedArray(2);
3625 details->set(0, Runtime::GetElementOrCharAt(obj, index));
3626 details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
3627 return *Factory::NewJSArrayWithElements(details);
3628 }
3629
3630 // Perform standard local lookup on the object.
3631 LookupResult result;
3632 obj->LocalLookup(*name, &result);
3633 if (result.IsProperty()) {
3634 Handle<Object> value(DebugLookupResultValue(&result));
3635 Handle<FixedArray> details = Factory::NewFixedArray(2);
3636 details->set(0, *value);
3637 details->set(1, result.GetPropertyDetails().AsSmi());
3638 return *Factory::NewJSArrayWithElements(details);
3639 }
3640 return Heap::undefined_value();
3641}
3642
3643
3644static Object* Runtime_DebugGetProperty(Arguments args) {
3645 HandleScope scope;
3646
3647 ASSERT(args.length() == 2);
3648
3649 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3650 CONVERT_ARG_CHECKED(String, name, 1);
3651
3652 LookupResult result;
3653 obj->Lookup(*name, &result);
3654 if (result.IsProperty()) {
3655 return DebugLookupResultValue(&result);
3656 }
3657 return Heap::undefined_value();
3658}
3659
3660
3661// Return the names of the local named properties.
3662// args[0]: object
3663static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
3664 HandleScope scope;
3665 ASSERT(args.length() == 1);
3666 if (!args[0]->IsJSObject()) {
3667 return Heap::undefined_value();
3668 }
3669 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3670
3671 int n = obj->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
3672 Handle<FixedArray> names = Factory::NewFixedArray(n);
3673 obj->GetLocalPropertyNames(*names);
3674 return *Factory::NewJSArrayWithElements(names);
3675}
3676
3677
3678// Return the names of the local indexed properties.
3679// args[0]: object
3680static Object* Runtime_DebugLocalElementNames(Arguments args) {
3681 HandleScope scope;
3682 ASSERT(args.length() == 1);
3683 if (!args[0]->IsJSObject()) {
3684 return Heap::undefined_value();
3685 }
3686 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3687
3688 int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
3689 Handle<FixedArray> names = Factory::NewFixedArray(n);
3690 obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
3691 return *Factory::NewJSArrayWithElements(names);
3692}
3693
3694
3695// Return the property type calculated from the property details.
3696// args[0]: smi with property details.
3697static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
3698 ASSERT(args.length() == 1);
3699 CONVERT_CHECKED(Smi, details, args[0]);
3700 PropertyType type = PropertyDetails(details).type();
3701 return Smi::FromInt(static_cast<int>(type));
3702}
3703
3704
3705// Return the property attribute calculated from the property details.
3706// args[0]: smi with property details.
3707static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) {
3708 ASSERT(args.length() == 1);
3709 CONVERT_CHECKED(Smi, details, args[0]);
3710 PropertyAttributes attributes = PropertyDetails(details).attributes();
3711 return Smi::FromInt(static_cast<int>(attributes));
3712}
3713
3714
3715// Return the property insertion index calculated from the property details.
3716// args[0]: smi with property details.
3717static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
3718 ASSERT(args.length() == 1);
3719 CONVERT_CHECKED(Smi, details, args[0]);
3720 int index = PropertyDetails(details).index();
3721 return Smi::FromInt(index);
3722}
3723
3724
3725// Return information on whether an object has a named or indexed interceptor.
3726// args[0]: object
3727static Object* Runtime_DebugInterceptorInfo(Arguments args) {
3728 HandleScope scope;
3729 ASSERT(args.length() == 1);
3730 if (!args[0]->IsJSObject()) {
3731 return Smi::FromInt(0);
3732 }
3733 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3734
3735 int result = 0;
3736 if (obj->HasNamedInterceptor()) result |= 2;
3737 if (obj->HasIndexedInterceptor()) result |= 1;
3738
3739 return Smi::FromInt(result);
3740}
3741
3742
3743// Return property names from named interceptor.
3744// args[0]: object
3745static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
3746 HandleScope scope;
3747 ASSERT(args.length() == 1);
3748 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3749 RUNTIME_ASSERT(obj->HasNamedInterceptor());
3750
3751 v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
3752 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
3753 return Heap::undefined_value();
3754}
3755
3756
3757// Return element names from indexed interceptor.
3758// args[0]: object
3759static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
3760 HandleScope scope;
3761 ASSERT(args.length() == 1);
3762 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3763 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
3764
3765 v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
3766 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
3767 return Heap::undefined_value();
3768}
3769
3770
3771// Return property value from named interceptor.
3772// args[0]: object
3773// args[1]: property name
3774static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
3775 HandleScope scope;
3776 ASSERT(args.length() == 2);
3777 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3778 RUNTIME_ASSERT(obj->HasNamedInterceptor());
3779 CONVERT_ARG_CHECKED(String, name, 1);
3780
3781 PropertyAttributes attributes;
3782 Object* result = obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
3783 return result;
3784}
3785
3786
3787// Return element value from indexed interceptor.
3788// args[0]: object
3789// args[1]: index
3790static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) {
3791 HandleScope scope;
3792 ASSERT(args.length() == 2);
3793 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3794 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
3795 CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
3796
3797 Object* result = obj->GetElementWithInterceptor(*obj, index);
3798 return result;
3799}
3800
3801
3802static Object* Runtime_CheckExecutionState(Arguments args) {
3803 ASSERT(args.length() >= 1);
3804 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
3805 // Check that the break id is valid and that there is a valid frame
3806 // where execution is broken.
3807 if (break_id != Top::break_id() ||
3808 Top::break_frame_id() == StackFrame::NO_ID) {
3809 return Top::Throw(Heap::illegal_execution_state_symbol());
3810 }
3811
3812 return Heap::true_value();
3813}
3814
3815
3816static Object* Runtime_GetFrameCount(Arguments args) {
3817 HandleScope scope;
3818 ASSERT(args.length() == 1);
3819
3820 // Check arguments.
3821 Object* result = Runtime_CheckExecutionState(args);
3822 if (result->IsFailure()) return result;
3823
3824 // Count all frames which are relevant to debugging stack trace.
3825 int n = 0;
3826 StackFrame::Id id = Top::break_frame_id();
3827 for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
3828 return Smi::FromInt(n);
3829}
3830
3831
3832static const int kFrameDetailsFrameIdIndex = 0;
3833static const int kFrameDetailsReceiverIndex = 1;
3834static const int kFrameDetailsFunctionIndex = 2;
3835static const int kFrameDetailsArgumentCountIndex = 3;
3836static const int kFrameDetailsLocalCountIndex = 4;
3837static const int kFrameDetailsSourcePositionIndex = 5;
3838static const int kFrameDetailsConstructCallIndex = 6;
3839static const int kFrameDetailsDebuggerFrameIndex = 7;
3840static const int kFrameDetailsFirstDynamicIndex = 8;
3841
3842// Return an array with frame details
3843// args[0]: number: break id
3844// args[1]: number: frame index
3845//
3846// The array returned contains the following information:
3847// 0: Frame id
3848// 1: Receiver
3849// 2: Function
3850// 3: Argument count
3851// 4: Local count
3852// 5: Source position
3853// 6: Constructor call
3854// 7: Debugger frame
3855// Arguments name, value
3856// Locals name, value
3857static Object* Runtime_GetFrameDetails(Arguments args) {
3858 HandleScope scope;
3859 ASSERT(args.length() == 2);
3860
3861 // Check arguments.
3862 Object* result = Runtime_CheckExecutionState(args);
3863 if (result->IsFailure()) return result;
3864 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
3865
3866 // Find the relevant frame with the requested index.
3867 StackFrame::Id id = Top::break_frame_id();
3868 int count = 0;
3869 JavaScriptFrameIterator it(id);
3870 for (; !it.done(); it.Advance()) {
3871 if (count == index) break;
3872 count++;
3873 }
3874 if (it.done()) return Heap::undefined_value();
3875
3876 // Traverse the saved contexts chain to find the active context for the
3877 // selected frame.
3878 SaveContext* save = Top::save_context();
3879 while (save != NULL && reinterpret_cast<Address>(save) < it.frame()->sp()) {
3880 save = save->prev();
3881 }
3882
3883 // Get the frame id.
3884 Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
3885
3886 // Find source position.
3887 int position = it.frame()->FindCode()->SourcePosition(it.frame()->pc());
3888
3889 // Check for constructor frame.
3890 bool constructor = it.frame()->IsConstructor();
3891
3892 // Get code and read scope info from it for local variable information.
3893 Handle<Code> code(it.frame()->FindCode());
3894 ScopeInfo<> info(*code);
3895
3896 // Get the context.
3897 Handle<Context> context(Context::cast(it.frame()->context()));
3898
3899 // Get the locals names and values into a temporary array.
3900 //
3901 // TODO(1240907): Hide compiler-introduced stack variables
3902 // (e.g. .result)? For users of the debugger, they will probably be
3903 // confusing.
3904 Handle<FixedArray> locals = Factory::NewFixedArray(info.NumberOfLocals() * 2);
3905 for (int i = 0; i < info.NumberOfLocals(); i++) {
3906 // Name of the local.
3907 locals->set(i * 2, *info.LocalName(i));
3908
3909 // Fetch the value of the local - either from the stack or from a
3910 // heap-allocated context.
3911 if (i < info.number_of_stack_slots()) {
3912 locals->set(i * 2 + 1, it.frame()->GetExpression(i));
3913 } else {
3914 Handle<String> name = info.LocalName(i);
3915 // Traverse the context chain to the function context as all local
3916 // variables stored in the context will be on the function context.
3917 while (context->previous() != NULL) {
3918 context = Handle<Context>(context->previous());
3919 }
3920 ASSERT(context->is_function_context());
3921 locals->set(i * 2 + 1,
3922 context->get(ScopeInfo<>::ContextSlotIndex(*code, *name,
3923 NULL)));
3924 }
3925 }
3926
3927 // Now advance to the arguments adapter frame (if any). If contains all
3928 // the provided parameters and
3929
3930 // Now advance to the arguments adapter frame (if any). It contains all
3931 // the provided parameters whereas the function frame always have the number
3932 // of arguments matching the functions parameters. The rest of the
3933 // information (except for what is collected above) is the same.
3934 it.AdvanceToArgumentsFrame();
3935
3936 // Find the number of arguments to fill. At least fill the number of
3937 // parameters for the function and fill more if more parameters are provided.
3938 int argument_count = info.number_of_parameters();
3939 if (argument_count < it.frame()->GetProvidedParametersCount()) {
3940 argument_count = it.frame()->GetProvidedParametersCount();
3941 }
3942
3943 // Calculate the size of the result.
3944 int details_size = kFrameDetailsFirstDynamicIndex +
3945 2 * (argument_count + info.NumberOfLocals());
3946 Handle<FixedArray> details = Factory::NewFixedArray(details_size);
3947
3948 // Add the frame id.
3949 details->set(kFrameDetailsFrameIdIndex, *frame_id);
3950
3951 // Add the function (same as in function frame).
3952 details->set(kFrameDetailsFunctionIndex, it.frame()->function());
3953
3954 // Add the arguments count.
3955 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
3956
3957 // Add the locals count
3958 details->set(kFrameDetailsLocalCountIndex,
3959 Smi::FromInt(info.NumberOfLocals()));
3960
3961 // Add the source position.
3962 if (position != kNoPosition) {
3963 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
3964 } else {
3965 details->set(kFrameDetailsSourcePositionIndex, Heap::undefined_value());
3966 }
3967
3968 // Add the constructor information.
3969 details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
3970
3971 // Add information on whether this frame is invoked in the debugger context.
3972 details->set(kFrameDetailsDebuggerFrameIndex,
3973 Heap::ToBoolean(*save->context() == *Debug::debug_context()));
3974
3975 // Fill the dynamic part.
3976 int details_index = kFrameDetailsFirstDynamicIndex;
3977
3978 // Add arguments name and value.
3979 for (int i = 0; i < argument_count; i++) {
3980 // Name of the argument.
3981 if (i < info.number_of_parameters()) {
3982 details->set(details_index++, *info.parameter_name(i));
3983 } else {
3984 details->set(details_index++, Heap::undefined_value());
3985 }
3986
3987 // Parameter value.
3988 if (i < it.frame()->GetProvidedParametersCount()) {
3989 details->set(details_index++, it.frame()->GetParameter(i));
3990 } else {
3991 details->set(details_index++, Heap::undefined_value());
3992 }
3993 }
3994
3995 // Add locals name and value from the temporary copy from the function frame.
3996 for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
3997 details->set(details_index++, locals->get(i));
3998 }
3999
4000 // Add the receiver (same as in function frame).
4001 // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
4002 // THE FRAME ITERATOR TO WRAP THE RECEIVER.
4003 Handle<Object> receiver(it.frame()->receiver());
4004 if (!receiver->IsJSObject()) {
4005 // If the receiver is NOT a JSObject we have hit an optimization
4006 // where a value object is not converted into a wrapped JS objects.
4007 // To hide this optimization from the debugger, we wrap the receiver
4008 // by creating correct wrapper object based on the calling frame's
4009 // global context.
4010 it.Advance();
4011 Handle<Context> calling_frames_global_context(
4012 Context::cast(Context::cast(it.frame()->context())->global_context()));
4013 receiver = Factory::ToObject(receiver, calling_frames_global_context);
4014 }
4015 details->set(kFrameDetailsReceiverIndex, *receiver);
4016
4017 ASSERT_EQ(details_size, details_index);
4018 return *Factory::NewJSArrayWithElements(details);
4019}
4020
4021
4022static Object* Runtime_GetCFrames(Arguments args) {
4023 HandleScope scope;
4024 ASSERT(args.length() == 1);
4025 Object* result = Runtime_CheckExecutionState(args);
4026 if (result->IsFailure()) return result;
4027
4028 static const int kMaxCFramesSize = 200;
4029 OS::StackFrame frames[kMaxCFramesSize];
4030 int frames_count = OS::StackWalk(frames, kMaxCFramesSize);
4031 if (frames_count == OS::kStackWalkError) {
4032 return Heap::undefined_value();
4033 }
4034
4035 Handle<String> address_str = Factory::LookupAsciiSymbol("address");
4036 Handle<String> text_str = Factory::LookupAsciiSymbol("text");
4037 Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
4038 for (int i = 0; i < frames_count; i++) {
4039 Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
4040 frame_value->SetProperty(
4041 *address_str,
4042 *Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
4043 NONE);
4044
4045 // Get the stack walk text for this frame.
4046 Handle<String> frame_text;
4047 if (strlen(frames[i].text) > 0) {
4048 Vector<const char> str(frames[i].text, strlen(frames[i].text));
4049 frame_text = Factory::NewStringFromAscii(str);
4050 }
4051
4052 if (!frame_text.is_null()) {
4053 frame_value->SetProperty(*text_str, *frame_text, NONE);
4054 }
4055
4056 frames_array->set(i, *frame_value);
4057 }
4058 return *Factory::NewJSArrayWithElements(frames_array);
4059}
4060
4061
4062static Object* Runtime_GetBreakLocations(Arguments args) {
4063 HandleScope scope;
4064 ASSERT(args.length() == 1);
4065
4066 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
4067 Handle<SharedFunctionInfo> shared(raw_fun->shared());
4068 // Find the number of break points
4069 Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
4070 if (break_locations->IsUndefined()) return Heap::undefined_value();
4071 // Return array as JS array
4072 return *Factory::NewJSArrayWithElements(
4073 Handle<FixedArray>::cast(break_locations));
4074}
4075
4076
4077// Set a break point in a function
4078// args[0]: function
4079// args[1]: number: break source position (within the function source)
4080// args[2]: number: break point object
4081static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
4082 HandleScope scope;
4083 ASSERT(args.length() == 3);
4084 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
4085 Handle<SharedFunctionInfo> shared(raw_fun->shared());
4086 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
4087 RUNTIME_ASSERT(source_position >= 0);
4088 Handle<Object> break_point_object_arg = args.at<Object>(2);
4089
4090 // Set break point.
4091 Debug::SetBreakPoint(shared, source_position, break_point_object_arg);
4092
4093 return Heap::undefined_value();
4094}
4095
4096
4097static Object* FindSharedFunctionInfoInScript(Handle<Script> script,
4098 int position) {
4099 // Iterate the heap looking for SharedFunctionInfo generated from the
4100 // script. The inner most SharedFunctionInfo containing the source position
4101 // for the requested break point is found.
4102 // NOTE: This might reqire several heap iterations. If the SharedFunctionInfo
4103 // which is found is not compiled it is compiled and the heap is iterated
4104 // again as the compilation might create inner functions from the newly
4105 // compiled function and the actual requested break point might be in one of
4106 // these functions.
4107 bool done = false;
4108 // The current candidate for the source position:
4109 int target_start_position = kNoPosition;
4110 Handle<SharedFunctionInfo> target;
4111 // The current candidate for the last function in script:
4112 Handle<SharedFunctionInfo> last;
4113 while (!done) {
4114 HeapIterator iterator;
4115 while (iterator.has_next()) {
4116 HeapObject* obj = iterator.next();
4117 ASSERT(obj != NULL);
4118 if (obj->IsSharedFunctionInfo()) {
4119 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
4120 if (shared->script() == *script) {
4121 // If the SharedFunctionInfo found has the requested script data and
4122 // contains the source position it is a candidate.
4123 int start_position = shared->function_token_position();
4124 if (start_position == kNoPosition) {
4125 start_position = shared->start_position();
4126 }
4127 if (start_position <= position &&
4128 position <= shared->end_position()) {
4129 // If there is no candidate or this function is within the currrent
4130 // candidate this is the new candidate.
4131 if (target.is_null()) {
4132 target_start_position = start_position;
4133 target = shared;
4134 } else {
4135 if (target_start_position < start_position &&
4136 shared->end_position() < target->end_position()) {
4137 target_start_position = start_position;
4138 target = shared;
4139 }
4140 }
4141 }
4142
4143 // Keep track of the last function in the script.
4144 if (last.is_null() ||
4145 shared->end_position() > last->start_position()) {
4146 last = shared;
4147 }
4148 }
4149 }
4150 }
4151
4152 // Make sure some candidate is selected.
4153 if (target.is_null()) {
4154 if (!last.is_null()) {
4155 // Position after the last function - use last.
4156 target = last;
4157 } else {
4158 // Unable to find function - possibly script without any function.
4159 return Heap::undefined_value();
4160 }
4161 }
4162
4163 // If the candidate found is compiled we are done. NOTE: when lazy
4164 // compilation of inner functions is introduced some additional checking
4165 // needs to be done here to compile inner functions.
4166 done = target->is_compiled();
4167 if (!done) {
4168 // If the candidate is not compiled compile it to reveal any inner
4169 // functions which might contain the requested source position.
4170 CompileLazyShared(target, KEEP_EXCEPTION);
4171 }
4172 }
4173
4174 return *target;
4175}
4176
4177
4178// Change the state of a break point in a script. NOTE: Regarding performance
4179// see the NOTE for GetScriptFromScriptData.
4180// args[0]: script to set break point in
4181// args[1]: number: break source position (within the script source)
4182// args[2]: number: break point object
4183static Object* Runtime_SetScriptBreakPoint(Arguments args) {
4184 HandleScope scope;
4185 ASSERT(args.length() == 3);
4186 CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
4187 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
4188 RUNTIME_ASSERT(source_position >= 0);
4189 Handle<Object> break_point_object_arg = args.at<Object>(2);
4190
4191 // Get the script from the script wrapper.
4192 RUNTIME_ASSERT(wrapper->value()->IsScript());
4193 Handle<Script> script(Script::cast(wrapper->value()));
4194
4195 Object* result = FindSharedFunctionInfoInScript(script, source_position);
4196 if (!result->IsUndefined()) {
4197 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
4198 // Find position within function. The script position might be before the
4199 // source position of the first function.
4200 int position;
4201 if (shared->start_position() > source_position) {
4202 position = 0;
4203 } else {
4204 position = source_position - shared->start_position();
4205 }
4206 Debug::SetBreakPoint(shared, position, break_point_object_arg);
4207 }
4208 return Heap::undefined_value();
4209}
4210
4211
4212// Clear a break point
4213// args[0]: number: break point object
4214static Object* Runtime_ClearBreakPoint(Arguments args) {
4215 HandleScope scope;
4216 ASSERT(args.length() == 1);
4217 Handle<Object> break_point_object_arg = args.at<Object>(0);
4218
4219 // Clear break point.
4220 Debug::ClearBreakPoint(break_point_object_arg);
4221
4222 return Heap::undefined_value();
4223}
4224
4225
4226// Change the state of break on exceptions
4227// args[0]: boolean indicating uncaught exceptions
4228// args[1]: boolean indicating on/off
4229static Object* Runtime_ChangeBreakOnException(Arguments args) {
4230 HandleScope scope;
4231 ASSERT(args.length() == 2);
4232 ASSERT(args[0]->IsNumber());
4233 ASSERT(args[1]->IsBoolean());
4234
4235 // Update break point state
4236 ExceptionBreakType type =
4237 static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
4238 bool enable = args[1]->ToBoolean()->IsTrue();
4239 Debug::ChangeBreakOnException(type, enable);
4240 return Heap::undefined_value();
4241}
4242
4243
4244// Prepare for stepping
4245// args[0]: break id for checking execution state
4246// args[1]: step action from the enumeration StepAction
4247// args[2]: number of times to perform the step
4248static Object* Runtime_PrepareStep(Arguments args) {
4249 HandleScope scope;
4250 ASSERT(args.length() == 3);
4251 // Check arguments.
4252 Object* check_result = Runtime_CheckExecutionState(args);
4253 if (check_result->IsFailure()) return check_result;
4254 if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
4255 return Top::Throw(Heap::illegal_argument_symbol());
4256 }
4257
4258 // Get the step action and check validity.
4259 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
4260 if (step_action != StepIn &&
4261 step_action != StepNext &&
4262 step_action != StepOut &&
4263 step_action != StepInMin &&
4264 step_action != StepMin) {
4265 return Top::Throw(Heap::illegal_argument_symbol());
4266 }
4267
4268 // Get the number of steps.
4269 int step_count = NumberToInt32(args[2]);
4270 if (step_count < 1) {
4271 return Top::Throw(Heap::illegal_argument_symbol());
4272 }
4273
4274 // Prepare step.
4275 Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
4276 return Heap::undefined_value();
4277}
4278
4279
4280// Clear all stepping set by PrepareStep.
4281static Object* Runtime_ClearStepping(Arguments args) {
4282 HandleScope scope;
4283 ASSERT(args.length() == 1);
4284 Debug::ClearStepping();
4285 return Heap::undefined_value();
4286}
4287
4288
4289// Creates a copy of the with context chain. The copy of the context chain is
4290// is linked to the function context supplied.
4291static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
4292 Handle<Context> function_context) {
4293 // At the bottom of the chain. Return the function context to link to.
4294 if (context_chain->is_function_context()) {
4295 return function_context;
4296 }
4297
4298 // Recursively copy the with contexts.
4299 Handle<Context> previous(context_chain->previous());
4300 Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
4301 return Factory::NewWithContext(
4302 CopyWithContextChain(function_context, previous), extension);
4303}
4304
4305
4306// Helper function to find or create the arguments object for
4307// Runtime_DebugEvaluate.
4308static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
4309 Handle<JSFunction> function,
4310 Handle<Code> code,
4311 const ScopeInfo<>* sinfo,
4312 Handle<Context> function_context) {
4313 // Try to find the value of 'arguments' to pass as parameter. If it is not
4314 // found (that is the debugged function does not reference 'arguments' and
4315 // does not support eval) then create an 'arguments' object.
4316 int index;
4317 if (sinfo->number_of_stack_slots() > 0) {
4318 index = ScopeInfo<>::StackSlotIndex(*code, Heap::arguments_symbol());
4319 if (index != -1) {
4320 return Handle<Object>(frame->GetExpression(index));
4321 }
4322 }
4323
4324 if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
4325 index = ScopeInfo<>::ContextSlotIndex(*code, Heap::arguments_symbol(),
4326 NULL);
4327 if (index != -1) {
4328 return Handle<Object>(function_context->get(index));
4329 }
4330 }
4331
4332 const int length = frame->GetProvidedParametersCount();
4333 Handle<Object> arguments = Factory::NewArgumentsObject(function, length);
4334 FixedArray* array = FixedArray::cast(JSObject::cast(*arguments)->elements());
4335 ASSERT(array->length() == length);
4336 for (int i = 0; i < length; i++) {
4337 array->set(i, frame->GetParameter(i));
4338 }
4339 return arguments;
4340}
4341
4342
4343// Evaluate a piece of JavaScript in the context of a stack frame for
4344// debugging. This is acomplished by creating a new context which in its
4345// extension part has all the parameters and locals of the function on the
4346// stack frame. A function which calls eval with the code to evaluate is then
4347// compiled in this context and called in this context. As this context
4348// replaces the context of the function on the stack frame a new (empty)
4349// function is created as well to be used as the closure for the context.
4350// This function and the context acts as replacements for the function on the
4351// stack frame presenting the same view of the values of parameters and
4352// local variables as if the piece of JavaScript was evaluated at the point
4353// where the function on the stack frame is currently stopped.
4354static Object* Runtime_DebugEvaluate(Arguments args) {
4355 HandleScope scope;
4356
4357 // Check the execution state and decode arguments frame and source to be
4358 // evaluated.
4359 ASSERT(args.length() == 3);
4360 Object* check_result = Runtime_CheckExecutionState(args);
4361 if (check_result->IsFailure()) return check_result;
4362 CONVERT_CHECKED(Smi, wrapped_id, args[1]);
4363 CONVERT_ARG_CHECKED(String, source, 2);
4364
4365 // Get the frame where the debugging is performed.
4366 StackFrame::Id id = UnwrapFrameId(wrapped_id);
4367 JavaScriptFrameIterator it(id);
4368 JavaScriptFrame* frame = it.frame();
4369 Handle<JSFunction> function(JSFunction::cast(frame->function()));
4370 Handle<Code> code(function->code());
4371 ScopeInfo<> sinfo(*code);
4372
4373 // Traverse the saved contexts chain to find the active context for the
4374 // selected frame.
4375 SaveContext* save = Top::save_context();
4376 while (save != NULL && reinterpret_cast<Address>(save) < frame->sp()) {
4377 save = save->prev();
4378 }
4379 ASSERT(save != NULL);
4380 SaveContext savex;
4381 Top::set_context(*(save->context()));
4382 Top::set_security_context(*(save->security_context()));
4383
4384 // Create the (empty) function replacing the function on the stack frame for
4385 // the purpose of evaluating in the context created below. It is important
4386 // that this function does not describe any parameters and local variables
4387 // in the context. If it does then this will cause problems with the lookup
4388 // in Context::Lookup, where context slots for parameters and local variables
4389 // are looked at before the extension object.
4390 Handle<JSFunction> go_between =
4391 Factory::NewFunction(Factory::empty_string(), Factory::undefined_value());
4392 go_between->set_context(function->context());
4393#ifdef DEBUG
4394 ScopeInfo<> go_between_sinfo(go_between->shared()->code());
4395 ASSERT(go_between_sinfo.number_of_parameters() == 0);
4396 ASSERT(go_between_sinfo.number_of_context_slots() == 0);
4397#endif
4398
4399 // Allocate and initialize a context extension object with all the
4400 // arguments, stack locals heap locals and extension properties of the
4401 // debugged function.
4402 Handle<JSObject> context_ext = Factory::NewJSObject(Top::object_function());
4403 // First fill all parameters to the context extension.
4404 for (int i = 0; i < sinfo.number_of_parameters(); ++i) {
4405 SetProperty(context_ext,
4406 sinfo.parameter_name(i),
4407 Handle<Object>(frame->GetParameter(i)), NONE);
4408 }
4409 // Second fill all stack locals to the context extension.
4410 for (int i = 0; i < sinfo.number_of_stack_slots(); i++) {
4411 SetProperty(context_ext,
4412 sinfo.stack_slot_name(i),
4413 Handle<Object>(frame->GetExpression(i)), NONE);
4414 }
4415 // Third fill all context locals to the context extension.
4416 Handle<Context> frame_context(Context::cast(frame->context()));
4417 Handle<Context> function_context(frame_context->fcontext());
4418 for (int i = Context::MIN_CONTEXT_SLOTS;
4419 i < sinfo.number_of_context_slots();
4420 ++i) {
4421 int context_index =
4422 ScopeInfo<>::ContextSlotIndex(*code, *sinfo.context_slot_name(i), NULL);
4423 SetProperty(context_ext,
4424 sinfo.context_slot_name(i),
4425 Handle<Object>(function_context->get(context_index)), NONE);
4426 }
4427 // Finally copy any properties from the function context extension. This will
4428 // be variables introduced by eval.
4429 if (function_context->extension() != NULL &&
4430 !function_context->IsGlobalContext()) {
4431 Handle<JSObject> ext(JSObject::cast(function_context->extension()));
4432 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
4433 for (int i = 0; i < keys->length(); i++) {
4434 // Names of variables introduced by eval are strings.
4435 ASSERT(keys->get(i)->IsString());
4436 Handle<String> key(String::cast(keys->get(i)));
4437 SetProperty(context_ext, key, GetProperty(ext, key), NONE);
4438 }
4439 }
4440
4441 // Allocate a new context for the debug evaluation and set the extension
4442 // object build.
4443 Handle<Context> context =
4444 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between);
4445 context->set_extension(*context_ext);
4446 // Copy any with contexts present and chain them in front of this context.
4447 context = CopyWithContextChain(frame_context, context);
4448
4449 // Wrap the evaluation statement in a new function compiled in the newly
4450 // created context. The function has one parameter which has to be called
4451 // 'arguments'. This it to have access to what would have been 'arguments' in
4452 // the function beeing debugged.
4453 // function(arguments,__source__) {return eval(__source__);}
4454 static const char* source_str =
4455 "function(arguments,__source__){return eval(__source__);}";
4456 static const int source_str_length = strlen(source_str);
4457 Handle<String> function_source =
4458 Factory::NewStringFromAscii(Vector<const char>(source_str,
4459 source_str_length));
4460 Handle<JSFunction> boilerplate =
4461 Compiler::CompileEval(context->IsGlobalContext(), function_source);
4462 if (boilerplate.is_null()) return Failure::Exception();
4463 Handle<JSFunction> compiled_function =
4464 Factory::NewFunctionFromBoilerplate(boilerplate, context);
4465
4466 // Invoke the result of the compilation to get the evaluation function.
4467 bool has_pending_exception;
4468 Handle<Object> receiver(frame->receiver());
4469 Handle<Object> evaluation_function =
4470 Execution::Call(compiled_function, receiver, 0, NULL,
4471 &has_pending_exception);
4472
4473 Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
4474 function_context);
4475
4476 // Invoke the evaluation function and return the result.
4477 const int argc = 2;
4478 Object** argv[argc] = { arguments.location(),
4479 Handle<Object>::cast(source).location() };
4480 Handle<Object> result =
4481 Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
4482 argc, argv, &has_pending_exception);
4483 return *result;
4484}
4485
4486
4487static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
4488 HandleScope scope;
4489
4490 // Check the execution state and decode arguments frame and source to be
4491 // evaluated.
4492 ASSERT(args.length() == 2);
4493 Object* check_result = Runtime_CheckExecutionState(args);
4494 if (check_result->IsFailure()) return check_result;
4495 CONVERT_ARG_CHECKED(String, source, 1);
4496
4497 // Enter the top context from before the debugger was invoked.
4498 SaveContext save;
4499 SaveContext* top = &save;
4500 while (top != NULL && *top->context() == *Debug::debug_context()) {
4501 top = top->prev();
4502 }
4503 if (top != NULL) {
4504 Top::set_context(*top->context());
4505 Top::set_security_context(*top->security_context());
4506 }
4507
4508 // Get the global context now set to the top context from before the
4509 // debugger was invoked.
4510 Handle<Context> context = Top::global_context();
4511
4512 // Compile the source to be evaluated.
4513 Handle<JSFunction> boilerplate(Compiler::CompileEval(true, source));
4514 if (boilerplate.is_null()) return Failure::Exception();
4515 Handle<JSFunction> compiled_function =
4516 Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
4517 context));
4518
4519 // Invoke the result of the compilation to get the evaluation function.
4520 bool has_pending_exception;
4521 Handle<Object> receiver = Top::global();
4522 Handle<Object> result =
4523 Execution::Call(compiled_function, receiver, 0, NULL,
4524 &has_pending_exception);
4525 return *result;
4526}
4527
4528
4529// Helper function used by Runtime_DebugGetLoadedScripts below.
4530static int DebugGetLoadedScripts(FixedArray* instances, int instances_size) {
4531 NoHandleAllocation ha;
4532 AssertNoAllocation no_alloc;
4533
4534 // Get hold of the current empty script.
4535 Context* context = Top::context()->global_context();
4536 Script* empty = context->empty_script();
4537
4538 // Scan heap for Script objects.
4539 int count = 0;
4540 HeapIterator iterator;
4541 while (iterator.has_next()) {
4542 HeapObject* obj = iterator.next();
4543 ASSERT(obj != NULL);
4544 if (obj->IsScript() && obj != empty) {
4545 if (instances != NULL && count < instances_size) {
4546 instances->set(count, obj);
4547 }
4548 count++;
4549 }
4550 }
4551
4552 return count;
4553}
4554
4555
4556static Object* Runtime_DebugGetLoadedScripts(Arguments args) {
4557 HandleScope scope;
4558 ASSERT(args.length() == 1);
4559
4560 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
4561 // rid of all the cached script wrappes and the second gets rid of the
4562 // scripts which is no longer referenced.
4563 Heap::CollectGarbage(0, OLD_SPACE);
4564 Heap::CollectGarbage(0, OLD_SPACE);
4565
4566 // Get the number of scripts.
4567 int count;
4568 count = DebugGetLoadedScripts(NULL, 0);
4569
4570 // Allocate an array to hold the result.
4571 Handle<FixedArray> instances = Factory::NewFixedArray(count);
4572
4573 // Fill the script objects.
4574 count = DebugGetLoadedScripts(*instances, count);
4575
4576 // Convert the script objects to proper JS objects.
4577 for (int i = 0; i < count; i++) {
4578 Handle<Script> script(Script::cast(instances->get(i)));
4579 instances->set(i, *GetScriptWrapper(script));
4580 }
4581
4582 // Return result as a JS array.
4583 Handle<JSObject> result = Factory::NewJSObject(Top::array_function());
4584 Handle<JSArray>::cast(result)->SetContent(*instances);
4585 return *result;
4586}
4587
4588
4589// Helper function used by Runtime_DebugReferencedBy below.
4590static int DebugReferencedBy(JSObject* target,
4591 Object* instance_filter, int max_references,
4592 FixedArray* instances, int instances_size,
4593 JSFunction* context_extension_function,
4594 JSFunction* arguments_function) {
4595 NoHandleAllocation ha;
4596 AssertNoAllocation no_alloc;
4597
4598 // Iterate the heap.
4599 int count = 0;
4600 JSObject* last = NULL;
4601 HeapIterator iterator;
4602 while (iterator.has_next() &&
4603 (max_references == 0 || count < max_references)) {
4604 // Only look at all JSObjects.
4605 HeapObject* heap_obj = iterator.next();
4606 if (heap_obj->IsJSObject()) {
4607 // Skip context extension objects and argument arrays as these are
4608 // checked in the context of functions using them.
4609 JSObject* obj = JSObject::cast(heap_obj);
4610 if (obj->map()->constructor() == context_extension_function ||
4611 obj->map()->constructor() == arguments_function) {
4612 continue;
4613 }
4614
4615 // Check if the JS object has a reference to the object looked for.
4616 if (obj->ReferencesObject(target)) {
4617 // Check instance filter if supplied. This is normally used to avoid
4618 // references from mirror objects (see Runtime_IsInPrototypeChain).
4619 if (!instance_filter->IsUndefined()) {
4620 Object* V = obj;
4621 while (true) {
4622 Object* prototype = V->GetPrototype();
4623 if (prototype->IsNull()) {
4624 break;
4625 }
4626 if (instance_filter == prototype) {
4627 obj = NULL; // Don't add this object.
4628 break;
4629 }
4630 V = prototype;
4631 }
4632 }
4633
4634 if (obj != NULL) {
4635 // Valid reference found add to instance array if supplied an update
4636 // count.
4637 if (instances != NULL && count < instances_size) {
4638 instances->set(count, obj);
4639 }
4640 last = obj;
4641 count++;
4642 }
4643 }
4644 }
4645 }
4646
4647 // Check for circular reference only. This can happen when the object is only
4648 // referenced from mirrors and has a circular reference in which case the
4649 // object is not really alive and would have been garbage collected if not
4650 // referenced from the mirror.
4651 if (count == 1 && last == target) {
4652 count = 0;
4653 }
4654
4655 // Return the number of referencing objects found.
4656 return count;
4657}
4658
4659
4660// Scan the heap for objects with direct references to an object
4661// args[0]: the object to find references to
4662// args[1]: constructor function for instances to exclude (Mirror)
4663// args[2]: the the maximum number of objects to return
4664static Object* Runtime_DebugReferencedBy(Arguments args) {
4665 ASSERT(args.length() == 3);
4666
4667 // First perform a full GC in order to avoid references from dead objects.
4668 Heap::CollectGarbage(0, OLD_SPACE);
4669
4670 // Check parameters.
4671 CONVERT_CHECKED(JSObject, target, args[0]);
4672 Object* instance_filter = args[1];
4673 RUNTIME_ASSERT(instance_filter->IsUndefined() ||
4674 instance_filter->IsJSObject());
4675 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
4676 RUNTIME_ASSERT(max_references >= 0);
4677
4678 // Get the constructor function for context extension and arguments array.
4679 JSFunction* context_extension_function =
4680 Top::context()->global_context()->context_extension_function();
4681 JSObject* arguments_boilerplate =
4682 Top::context()->global_context()->arguments_boilerplate();
4683 JSFunction* arguments_function =
4684 JSFunction::cast(arguments_boilerplate->map()->constructor());
4685
4686 // Get the number of referencing objects.
4687 int count;
4688 count = DebugReferencedBy(target, instance_filter, max_references,
4689 NULL, 0,
4690 context_extension_function, arguments_function);
4691
4692 // Allocate an array to hold the result.
4693 Object* object = Heap::AllocateFixedArray(count);
4694 if (object->IsFailure()) return object;
4695 FixedArray* instances = FixedArray::cast(object);
4696
4697 // Fill the referencing objects.
4698 count = DebugReferencedBy(target, instance_filter, max_references,
4699 instances, count,
4700 context_extension_function, arguments_function);
4701
4702 // Return result as JS array.
4703 Object* result =
4704 Heap::AllocateJSObject(
4705 Top::context()->global_context()->array_function());
4706 if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
4707 return result;
4708}
4709
4710
4711// Helper function used by Runtime_DebugConstructedBy below.
4712static int DebugConstructedBy(JSFunction* constructor, int max_references,
4713 FixedArray* instances, int instances_size) {
4714 AssertNoAllocation no_alloc;
4715
4716 // Iterate the heap.
4717 int count = 0;
4718 HeapIterator iterator;
4719 while (iterator.has_next() &&
4720 (max_references == 0 || count < max_references)) {
4721 // Only look at all JSObjects.
4722 HeapObject* heap_obj = iterator.next();
4723 if (heap_obj->IsJSObject()) {
4724 JSObject* obj = JSObject::cast(heap_obj);
4725 if (obj->map()->constructor() == constructor) {
4726 // Valid reference found add to instance array if supplied an update
4727 // count.
4728 if (instances != NULL && count < instances_size) {
4729 instances->set(count, obj);
4730 }
4731 count++;
4732 }
4733 }
4734 }
4735
4736 // Return the number of referencing objects found.
4737 return count;
4738}
4739
4740
4741// Scan the heap for objects constructed by a specific function.
4742// args[0]: the constructor to find instances of
4743// args[1]: the the maximum number of objects to return
4744static Object* Runtime_DebugConstructedBy(Arguments args) {
4745 ASSERT(args.length() == 2);
4746
4747 // First perform a full GC in order to avoid dead objects.
4748 Heap::CollectGarbage(0, OLD_SPACE);
4749
4750 // Check parameters.
4751 CONVERT_CHECKED(JSFunction, constructor, args[0]);
4752 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
4753 RUNTIME_ASSERT(max_references >= 0);
4754
4755 // Get the number of referencing objects.
4756 int count;
4757 count = DebugConstructedBy(constructor, max_references, NULL, 0);
4758
4759 // Allocate an array to hold the result.
4760 Object* object = Heap::AllocateFixedArray(count);
4761 if (object->IsFailure()) return object;
4762 FixedArray* instances = FixedArray::cast(object);
4763
4764 // Fill the referencing objects.
4765 count = DebugConstructedBy(constructor, max_references, instances, count);
4766
4767 // Return result as JS array.
4768 Object* result =
4769 Heap::AllocateJSObject(
4770 Top::context()->global_context()->array_function());
4771 if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
4772 return result;
4773}
4774
4775
4776static Object* Runtime_GetPrototype(Arguments args) {
4777 ASSERT(args.length() == 1);
4778
4779 CONVERT_CHECKED(JSObject, obj, args[0]);
4780
4781 return obj->GetPrototype();
4782}
4783
4784
4785static Object* Runtime_SystemBreak(Arguments args) {
4786 CPU::DebugBreak();
4787 return Heap::undefined_value();
4788}
4789
4790
4791// Finds the script object from the script data. NOTE: This operation uses
4792// heap traversal to find the function generated for the source position
4793// for the requested break point. For lazily compiled functions several heap
4794// traversals might be required rendering this operation as a rather slow
4795// operation. However for setting break points which is normally done through
4796// some kind of user interaction the performance is not crucial.
4797static Handle<Object> Runtime_GetScriptFromScriptName(
4798 Handle<String> script_name) {
4799 // Scan the heap for Script objects to find the script with the requested
4800 // script data.
4801 Handle<Script> script;
4802 HeapIterator iterator;
4803 while (script.is_null() && iterator.has_next()) {
4804 HeapObject* obj = iterator.next();
4805 // If a script is found check if it has the script data requested.
4806 if (obj->IsScript()) {
4807 if (Script::cast(obj)->name()->IsString()) {
4808 if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
4809 script = Handle<Script>(Script::cast(obj));
4810 }
4811 }
4812 }
4813 }
4814
4815 // If no script with the requested script data is found return undefined.
4816 if (script.is_null()) return Factory::undefined_value();
4817
4818 // Return the script found.
4819 return GetScriptWrapper(script);
4820}
4821
4822
4823// Get the script object from script data. NOTE: Regarding performance
4824// see the NOTE for GetScriptFromScriptData.
4825// args[0]: script data for the script to find the source for
4826static Object* Runtime_GetScript(Arguments args) {
4827 HandleScope scope;
4828
4829 ASSERT(args.length() == 1);
4830
4831 CONVERT_CHECKED(String, script_name, args[0]);
4832
4833 // Find the requested script.
4834 Handle<Object> result =
4835 Runtime_GetScriptFromScriptName(Handle<String>(script_name));
4836 return *result;
4837}
4838
4839
4840static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
4841#ifdef DEBUG
4842 HandleScope scope;
4843 ASSERT(args.length() == 1);
4844 // Get the function and make sure it is compiled.
4845 CONVERT_ARG_CHECKED(JSFunction, func, 0);
4846 if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
4847 return Failure::Exception();
4848 }
4849 func->code()->PrintLn();
4850#endif // DEBUG
4851 return Heap::undefined_value();
4852}
4853
4854
4855static Object* Runtime_Abort(Arguments args) {
4856 ASSERT(args.length() == 2);
4857 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
4858 Smi::cast(args[1])->value());
4859 Top::PrintStack();
4860 OS::Abort();
4861 UNREACHABLE();
4862 return NULL;
4863}
4864
4865
4866static Object* Runtime_ListNatives(Arguments args) {
4867 ASSERT(args.length() == 1);
4868 HandleScope scope;
4869 Handle<JSArray> result = Factory::NewJSArray(0);
4870 int index = 0;
4871#define ADD_ENTRY(Name, argc) \
4872 { \
4873 HandleScope inner; \
4874 Handle<String> name = \
4875 Factory::NewStringFromAscii(Vector<const char>(#Name, strlen(#Name))); \
4876 Handle<JSArray> pair = Factory::NewJSArray(0); \
4877 SetElement(pair, 0, name); \
4878 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \
4879 SetElement(result, index++, pair); \
4880 }
4881 RUNTIME_FUNCTION_LIST(ADD_ENTRY)
4882#undef ADD_ENTRY
4883 return *result;
4884}
4885
4886
4887static Object* Runtime_IS_VAR(Arguments args) {
4888 UNREACHABLE(); // implemented as macro in the parser
4889 return NULL;
4890}
4891
4892
4893// ----------------------------------------------------------------------------
4894// Implementation of Runtime
4895
4896#define F(name, nargs) \
4897 { #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \
4898 static_cast<int>(Runtime::k##name) },
4899
4900static Runtime::Function Runtime_functions[] = {
4901 RUNTIME_FUNCTION_LIST(F)
4902 { NULL, NULL, NULL, 0, -1 }
4903};
4904
4905#undef F
4906
4907
4908Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
4909 ASSERT(0 <= fid && fid < kNofFunctions);
4910 return &Runtime_functions[fid];
4911}
4912
4913
4914Runtime::Function* Runtime::FunctionForName(const char* name) {
4915 for (Function* f = Runtime_functions; f->name != NULL; f++) {
4916 if (strcmp(f->name, name) == 0) {
4917 return f;
4918 }
4919 }
4920 return NULL;
4921}
4922
4923
4924void Runtime::PerformGC(Object* result) {
4925 Failure* failure = Failure::cast(result);
4926 // Try to do a garbage collection; ignore it if it fails. The C
4927 // entry stub will throw an out-of-memory exception in that case.
4928 Heap::CollectGarbage(failure->requested(), failure->allocation_space());
4929}
4930
4931
4932} } // namespace v8::internal