Guillermo Polito
email: guillermo.polito@univ-lille.fr

Pablo Tesone
email: pablo.tesone@inria.fr

Stéphane Ducasse
email: stephane.ducasse@inria.fr

Interpreter-guided Differential JIT Compiler Unit Testing

Keywords: virtual machine, concolic testing, JIT compilers, interpreters PL'18

Modern language implementations using Virtual Machines feature diverse execution engines such as byte-code interpreters and machine-code dynamic translators, a.k.a. JIT compilers. Validating such engines requires not only validating each in isolation, but also that they are functionally equivalent. Tests should be duplicated for each execution engine exercising the same execution paths on each of them.

In this paper we present a novel automated testing approach for virtual machines featuring byte-code interpreters. Our solution uses concolic meta-interpretation: it applies concolic testing to a byte-code interpreter to explore all possible execution interpreter paths and obtain a list of concrete values that explore such paths. We then use such values to apply differential testing on the VM interpreter and JIT compiler. This solution is based on two insights: (1) both the interpreter and compiler implement the same language semantics and (2) interpreters are simple executable specifications of those semantics and thus promising targets to (meta-) interpretation using concolic testing. We validated it on 4 different compilers of the open-source Pharo Virtual Machine and found 468 differences between them, produced by 91 different causes, organized in 6 different categories.

Introduction

Modern Virtual Machines support code generation for JIT compilation and dynamic code patching for techniques such as inline caching. They are often structured around a bytecode interpreter, a baseline JIT compiler, and a speculative inliner. This complexity is aggravated when the VM builds and runs on multiple target architectures [START_REF] Alpern | Experiences porting the jikes rvm to linux/ia32[END_REF]. Validating the execution of interpreted code and its compiled counterpart is challenging.

Several solutions have been proposed to aid in VM testing tasks. Traditionally, VM simulation environments have appeared in Self [START_REF] Ungar | Constructing a metacircular virtual machine in an exploratory programming environment[END_REF], Smalltalk [START_REF] Ingalls | Back to the future: The story of Squeak, a practical Smalltalk written in itself[END_REF][START_REF] Miranda | Two decades of smalltalk vm development: live vm development through simulation tools[END_REF] and Metacircular VMs such as Maxine [START_REF] Wimmer | Maxine: An approachable virtual machine for, and in, java[END_REF]. Complementary to simulation environments, multi-level debuggers [START_REF] Kruck | Multi-level debugging for interpreter developers[END_REF][START_REF] Würthinger | Multi-level virtual machine debugging using the java platform debugger architecture[END_REF] aid VM developers to switch views between the program-level and the implementation (VM)-level. These solutions are indeed beneficial to identify and track problems once an issue has been spotted and reproduced. However, reproducing bugs still remains an expensive and time-consuming task because millions of instructions may need to be executed before hitting the actual problem. For example, it has been reported that debugging memory corruption bugs in a simulation could take several hours of execution 1 . Recently, the team of Maxine reported a test-based infrastructure for cross-ISA debugging [START_REF] Kotselidis | Cross-isa debugging in meta-circular vms[END_REF]. They reported that most debugging happens in gdb when bootstrapping a new architecture, in a different abstraction level than the original source code, and that they were not able to cover many parts of their codebase. Béra et al., [START_REF] Béra | Practical validation of bytecode to bytecode jit compiler dynamic deoptimization[END_REF] and Flückiger et al., [START_REF] Flückiger | Correctness of speculative optimizations with dynamic deoptimization[END_REF] focus on the validation interaction between speculative compiler transformations and deoptimization.

Moreover, Virtual Machines often include several execution engines with different trade-offs: it is common for example to mix byte-code interpretation for cold code, with Just in Time compilers that optimize hot code. Since these different components are meant to be semantically equivalent, test scenarios need to be duplicated too for each of them.

In this paper we propose to guide the automatic unit testing of a JIT compiler by the interpreter definition. Our technique is based on two insights. First, we consider interpreters executable specifications of the programming language semantics and thus we propose to use them to automatically generate test inputs. Second, since both the interpreter and compilers for a language should implement the same language semantics, we apply differential testing on them [START_REF] Mckeeman | Differential Testing for Software[END_REF], comparing their behavior as test oracles.

We first apply concolic testing on the interpreter to (1) discover all possible execution paths and (2) produce an abstract description of the input values. We then generate the compiled code for each case and exercise it each with values equivalent to those in the interpreter. Our path exploration differs from traditional concolic testing in that it does not stop as soon as it finds a concrete error. Instead, it tracks for each execution path an exit condition indicating how the instruction finished (e.g., success, failure), or if it exited the main interpreter for some runtime service (e.g., message send or method return). Tracking the exit condition allows us to test that the compiled code has the same observable behavior than the interpreted code.

We applied it to the byte-code interpreter and four different compilers of the Pharo Virtual Machine: both the native method template-based compiler and the stack-to-register byte-code compiler considered stable and in production since more than 10 years, plus two non-productive compilers. Our approach generated in less than 10 minutes more than 4.5K tests, and found 468 differences from 91 different causes.

The contributions of the article are:

• we show that interpreters are a valid resource when generating JIT compiler test inputs, unveiling many differences between them; • we show that our approach finds differences ranging from clear bugs producing segmentation faults, to optimisation and behavioural differences; • we are, to the best of our knowledge, the first to use concolic testing in the domain of Virtual Machines and JIT compilers; • we are, to the best of our knowledge, the first to combine concolic testing with differential testing to test compilers; • we show that the approach is practical and applicable on-line. Section 2 presents the problems and the solution for validating differences between interpreter and compiler. Section 3 describes the execution model that we designed to be able to capture the test domains (stack, operand, or format shapes). Section 4 describes the setup of our experience, while Section 5 describes the results obtained. Further sections present related work and conclude.

2 Interpreter-Guided differential VM Testing 2.1 Problem: Testing Duplicated Semantics in Virtual Machines Modern virtual machines include several execution engines with different trade-offs. It is common to have simple yet slow byte-code interpreters to execute code that is rarely found at run time, and one or more dynamic translation tiers that translate hot code to machine Just in time (JIT). Such a schema is designed to achieve a good balance between the time spent executing useful work and the time spent compiling to machine-code. A key challenge is to validate the correctness of these components that generally have few code in common and present very different architectures. For example, while a byte-code interpreter executes directly the byte-code, each compilation tier uses a different intermediate representation design.

Let us illustrate this difference with the interpreter implementation of the addition byte-code in the Pharo Virtual Machine shown in Listing 1. The addition byte-code is implemented in Pharo's interpreter using static type predictions, inlining the common case for integer arithmetics, and defaulting to user-defined methods if not suitable [START_REF] Chambers | Customization: Optimizing compiler technology for self, a dynamically-typed object-oriented programming language[END_REF][START_REF] Holzle | Adaptive Optimization for Self: Reconciling High Performance with Exploratory Programming[END_REF]. Such an instruction pops two elements from the operand stack, checks if they are both small integers and, if they are, it adds them up. If the result does not overflow, arguments are popped, the result is pushed to the operand stack, and execution continues with the next byte-code. If none of the conditions above hold, the instruction takes a slow path and performs a normal message send. 12 ^self fetchNextBytecode "success"]].

13

"Slow path, message send"

14 self normalSend
Listing 1. Excerpt of the byte-code interpretation implementing addition in the Pharo Virtual Machine.

At the same time, when the Pharo VM first-tier JIT compiler parses that byte-code it generates the sequence of intermediate representation (IR) instructions illustrated in Listing 5. Although those IR instructions are meant to be compiled to machine code, they conceptually represent the same behavior as in the interpreter: they perform type checks on the arguments and result, and fall back to a slower message send if any of those conditions do not hold. It is indeed possible to manually write tests for these components, but such manual specification is labor intensive and

Interpreter-Guided VM Testing

In this paper we use interpreter-guided differential testing between interpreter and JIT compiler to discover differences between them. Our approach is interpreter-guided in the sense that we use the interpreter implementation to direct automatic test case generation for the JIT compiler. This technique is based on the following insights. First, we consider Virtual Machine interpreters executable specifications of a language semantics [START_REF] Futamura | Partial evaluation of computation process: An approach to a compiler-compiler[END_REF]. Second, interpreters often implement complete semantics since they are the execution engine that a VM falls back into when the more complex tiers do not support a feature. Finally, since both interpreter and compilers should implement the same language semantics, comparing their behavior is useful as test oracles. Figure 1 illustrates our solution for one VM instruction. We first (step 1) perform a concolic execution [START_REF] Godefroid | Dart: directed automated random testing[END_REF][START_REF] Sen | Cute: A concolic unit testing engine for c[END_REF] of the interpreter instruction to discover the input values that exercise all of its execution paths. During our concolic execution, we record input and output constraints on both the VM state before and after the instruction. We then compile the instruction with the JIT compiler (step 2), use the input constraints to build concrete VM stack frames and execute the compiled code on it (step 3). Finally, we use the output constraints to validate that the compiled code had the same observable side effects on the stack frame (step 4).

Interpreter Concolic Testing

Concolic testing [START_REF] Godefroid | Dart: directed automated random testing[END_REF][START_REF] Sen | Cute: A concolic unit testing engine for c[END_REF] is an automated testing technique that combines concrete and symbolic execution of a program to generate input values that explore all of the program's possible execution paths. In a nutshell, concolic testing executes the program under test many times, each time with different concrete values. Each execution is instrumented to produce symbolic constraints and track all control flow conditions in so called path conditions. When the execution finishes, it negates the last path condition not already negated to explore a new path, and its constraints are fed to an automatic constraint solver. The values obtained from the automatic constraint solver are the inputs for the next iteration. The search finishes when all possible paths are explored.

In our example of bytecodePrimAdd above, applying concolic testing yields the results shown in Table 1. The first time, our VM concolic tester will execute the instruction push integers as arguments, and record that the execution checked that both are integers, and their sum is in range too. It then negates the last condition, and the constraint solver generates two integers that summed up generate an overflow. The code is re-executed with those values and no new constraints are found. It then negates the previous nonnegated condition and generates one integer argument and one non-integer argument. It continues in such a way until all paths are exercised.

Interpreter-Compiler Differential Testing

After compiling the code corresponding to an interpreter instruction using the JIT compiler, we perform a concrete execution using compiled code and compare its result with the interpreter result. The concrete execution requires to set up a concrete VM stack frame, created from the constraints recorded on the interpreter input frame.

Our approach does not require that interpreter and compiler have stack frames with the same shape. This is the case of our guiding example, where our interpreter implements a stack-based machine while our compiler is a register-based machine. In this case, it is the differential tester that interprets the input frame constraints and sets up a VM frame that suits the compiler structure and calling convention e.g., arguments should be pushed to the stack in the interpreter, while they need to be put in registers in the compiled version.

Execution Model

In this section we present our concolic execution model extended with Virtual Machine semantics.

Vocabulary: Byte-code and Native Methods

For clarity of the presentation, this subsection presents some vocabulary points. Our solution works with the compilation of two kind of instructions:

Byte-code instructions. Instructions used as a VM intermediate language. The programming language source code is compiled to a sequence of byte-code instructions e.g., push instance variable, duplicate the top of the stack. Byte-code instructions in our implementation are by design unsafe for performance reasons. For Each concolic execution starts with an abstract input frame, and produces an abstract output frame, an exit condition, and the recorded constraint path. Already negated conditions are in italics. The last not-already-negated constraint path is negated and leads to the next concolic path execution. example, a pop instruction does not validate the number of elements in the operand stack, assuming that values were pushed to the stack before its execution. Native Methods. Primitive operations exposed by the Virtual Machine as methods. Native methods are used implement basic functionality and natively optimised versions of some functionality e.g., computing trigonometric functions, object allocation. Native methods in our implementation are by design safe. They check the types and shapes of all their operands and fail with a failure code in case an operand is incorrect.

From the point of view of this paper, we will consider both byte-code and native methods as VM instructions. Some functionality in our VM implementation is provided as both byte-code instructions and native methods, duplicated for performance reasons e.g., integer addition. Moreover, native methods tend to be larger and more complex, as we present in Section 5.4.

Abstract Objects and Abstract Frames

Our constraint model represents path constraints together with VM object constraint, as depicted in Figure 3. We use VM object constraints to model dynamic VM data structures and keep a link to the flat constraint variables fed to the constraint solver. In this sense, re-creating a VM input implies interpreting the results of the constraint solver using the structural information in the VM object constraints. The core of our contraint model includes the abstract modeling of:

• VM stack frames with receiver object, method, locals, operand stack; • VM objects with their class, memory format, slots referencing other objects; • VM classes with their class table id. One key aspect of our solution is that we store copies of both the input and output constraints created during the concolic execution. Input constraints serve to re-create a concrete input frame to execute the compiled code. We use the stored output constraints to perform the differential validation and check that the compiled code has the same observable behavior as the interpreted code. Moreover, recording both input and output constraints for each concolic path execution requires storing a copy of each of them because VM instructions have side effects: if an instruction pushes a value to the operand stack or modifies a variable that is local to the frame, such modification must not alter the input frame. Figure 2 illustrates this with our guiding example i.e., integer addition. Each column in the figure illustrates one concolic path execution, for which it depicts: input frame, output frame, exit condition (e.g., whether the instruction finished with error or success), recorded constraint path and finally the negated constraint path that leads to the next concolic path execution.

Virtual Machine Constraints

The VM does ultimately treat objects as raw unstructured data through pointer arithmetics. This means that recording constraints at that low-level of abstraction would complicate object re-creation and misses semantic information that is important for condition negation during the concolic execution. For example, the VM concrete execution checks if a value is not an integer by checking if it is not a tagged value, which we could represent with a constraint (v && 1) == 1. However, negating that constraint obtains the constraint (v && 1) != 1, which does not correctly represent tagged integers: tagged integers need also to be within certain bounds.

To deal with this issue, our execution model models the VM semantics instead of the concrete memory manipulations done by the VM. In our example above, we record if an object is a tagged small integer or not using semantic conditions such as isSmallInteger(v) and isNotSmallInteger(v). Our semantic conditions includes conditions such as class index of, integer to float conversions, object-to-native data conversions, and so on.

Such a decoupling does help when negating conditions during the concolic execution, but also allows conditions to be address independent. This decoupling also makes our solution work on constraint solvers that do not support bitwise manipulations used not only for pointer tagging but also to extract object header meta-data.

Instruction Exit Conditions

Alongside the input and output constraints and the constraint paths, our concolic execution model tracks also the exit status of an instruction, as shown in Figure 2. An instruction exit status models how the instruction execution finished, allowing us to validate the behavioral equivalence between the interpreted and compiled versions. Moreover, it allows us to detect certain conditions from which the execution leaves the main interpreter to execute slower execution paths. Our concolic execution model tracks the following exit conditions: Success. Represents the correct execution of an instruction until its end. It is the main exit condition of byte-code instructions manipulating the operand stack (e.g., push, pop, dup) and of native methods. Successful executions should execute until the end in compiled byte-code, or return to the caller in compiled native methods. Failure. Represents the invalid attempt to execute a native method. As specified above, native methods in our model are safe: they check their operands' types and shape and fail if they are not as expected. Failing executions do fall-back to user defined code instead of returning to the caller.

Message Send. Represents the attempt to activate a messagesend. Several byte-code instructions perform method activations, either in their main execution path or as a slow path for optimized byte-code instructions. Message send executions should perform a call to a trampoline or to a method linked through mono-, poly-or mega-morphic inline caches [START_REF] Hölzle | Optimizing dynamically-typed object-oriented languages with polymorphic inline caches[END_REF]. Method Return. Represents the attempt to return to the caller. Returned executions should return to the caller both in interpreted and compiled methods. Invalid Frame. Represents the attempt to access a nonexisting value in the stack frame. Our concolic execution generates VM frames based on constraints, and thus it does only generate values in a frame if a constraint required so. An invalid frame exit indicates our concolic execution engine that subsequent executions need extra elements in the stack. We consider invalid frame exits as expected failures in our test runner. Invalid Memory Access. Represents the attempt to perform an out-of-bounds access on an object. Our concolic execution validates that object accesses are within bounds, and fails if not. An invalid memory access indicates our concolic execution engine that subsequent executions need more slots in an object. In our test runner we consider invalid memory access executions as expected failures for byte-code instructions because they are unsafe by design. However, we consider them as errors for native methods because native methods are supposed to validate accesses and fail instead of performing the invalid reads/writes.

Although not yet covered by our implementation, our model remains extensible with new exit conditions such as activating a garbage collection.

Realization

4.1 Experimentation Platform: Pharo VM Our experimentation platform is the Pharo Virtual Machine. The Pharo Virtual Machine is an industrial level Virtual Machine written in Pharo itself and transpiled to C using a VM-specific translator called Slang [START_REF] Ingalls | Back to the future: The story of Squeak, a practical Smalltalk written in itself[END_REF]. The VM implements at the core of its execution engine a threaded bytecode interpreter, a linear non-optimising JIT compiler named Cogit [START_REF] Miranda | The cog smalltalk virtual machine[END_REF] that includes polymorphic inline caches [START_REF] Hölzle | Optimizing dynamically-typed object-oriented languages with polymorphic inline caches[END_REF] and a generational scavenger garbage collector that uses a copy collector for young objects and a mark-compact collector for older objects [START_REF] Ungar | Generation scavenging: A non-disruptive high performance storage reclamation algorithm[END_REF]. The following numbers illustrate the complexity of this Virtual Machine:

• It implements 255 byte-codes, organized in a total of 77 different families [START_REF] Béra | A bytecode set for adaptive optimizations[END_REF]. • It implements about 340 native methods, several duplicated in both the interpreter and in the JIT compiler.

Experimental Compilers. The Pharo VM JIT compiler we test in our evaluation has different backends in charge of translating IR to Machine-Code specialized per target ISA, and three different front-ends: three byte-code compiler frontends and a native method compiler frontend. The byte-code compilers parse byte-code into IR through abstract interpretation. The byte-code compiler used in production (StackToRegisterCogit) performs a stack-to-register mapping using a parse-time stack, to avoid unnecessary stack accesses in the generated machine-code. We included in our evaluation two additional byte-code compilers not used in production: (a) the SimpleStackBasedCogit is a simpler version of the compiler that maps push and pop byte-code instructions to their equivalent push and pop machine-code instructions, and (b) the experimental RegisterAllocatingCogit extends the StackToRegisterCogit with a linear register allocator. Finally, native methods implementing primitive operations are translated to IR using a hand-written templatebased approach.

Pharo Testing Infrastructure. The Pharo VM presents a high-level simulation environment that is very handy to simulate full executions including JITt'ed code and liveprogram the VM [START_REF] Miranda | Two decades of smalltalk vm development: live vm development through simulation tools[END_REF], illustrated in Figure 4. The simulation environment is extended with a testing infrastructure [START_REF] Polito | Cross-ISA Testing of the Pharo VM: Lessons Learned While Porting to ARMv8[END_REF] that allows VM developers to write fine-grained testing scenarios, making tests small, fast, reproducible, and cross-ISA. The VM is executed as Pharo code in the simulation environment and transpiled to C to produce the production artefact. The testing infrastructure extends the simulation environment.

Compiling Instructions

The interpreted and compiled code present many semantic differences that our differential tester needs to deal with. First, interpreted byte-code is stack-based, while compiled code is mainly register-based. Second, the granularity of compiled code is the method, meaning that single instructions cannot be compiled in isolation. Last, but not least, our three experimental compilers generate code that has different behavior and expectations.

Compiling byte-code instructions. Pharo methods are compiled to stack-based byte-code instructions. The bytecode JIT compiler performs an abstract interpretation on the byte-code to generate the corresponding IR, and later perform code generation. However, as explained above in Section 4.1, our byte-code compilers behave differently regarding optimisation of stack access. Indeed the StackToReg-isterCogit will use a parse-time stack to simulate pushes, and only generate stack accesses if a corresponding pop instruction consumes the operands in the stack. As a corollary, when testing the compilation of instructions pushing values to the stack, we must ensure that those instructions are followed by instructions consuming those stack values.

We solved the challenges above by implementing the following compilation schema. First, when testing a byte-code instruction, our compilation unit is a method. The method will have as many arguments or locals as required by the instruction (e.g., to support a pushLocalVariable byte-code) and the compiler will ensure the method has a correct preamble. Second, we prepend in the method IR instructions that push literals to guarantee the shape of the operand stack. Compiling native method instructions. Native methods implement non-inlined versions of arithmetics, object and array accesses, reflection, and so on. The main difference between a native method and a byte-code instruction is that they are late-bound: what method is to be executed is defined from the type of the receiver object. This schema allows one to exploit polymorphism and operator redefinitions.

Pharo native methods are hybrid, they have a native behavior component and a byte-code component. On the one hand, native methods are interpreted by calling a VM function that manipulates the operand stack and returns to the caller if successful. If the native behavior fails, interpretation continues with byte-code execution of the user redefined method. On the other hand, JIT compiled native methods are a linear version of the above, where the machine-code method starts with a machine-code version of the native behavior, and falls through a compiled version of the byte-code in case of failure. Second, we made our differential tester to only compile the native behavior and introduce a breakpoint/stop instruction after the last instruction to detect fall-through cases. Then, for each test path, we assert that the compiled code returns to the caller if we had detected no error condition, or to hit the breakpoint instruction otherwise.

Current Prototype Limitations

Our concolic tester prototype does not currently support several features of the Pharo interpreter, namely stack-frame reifications and byte-code look-aheads. Moreover, the constraint solver we are using for the concolic exploration limits integers to 56 bit precision and does not support bit-wise operations. None of these limitations are essential to the approach, but they rather require additional engineering effort.

Stack-frame Reifications. Stack-frame reifications are implemented in the Pharo interpreter to support reflection on stack-frames, and the implementation of exceptions as a library rather than a language feature. The current implementation of stack-frame reifications implements lazy contextto-stack mapping [START_REF] Miranda | Context management in visualworks 5i[END_REF][START_REF] Miranda | The cog smalltalk virtual machine[END_REF]: context objects are heap allocated only on demand and work as proxies to a stack-frame for some of their life time. This means that the interpreter handles such mapping in several execution paths, particularly during explicit stack reification (i.e., the pushThisContext byte-code instruction) and during instance variable access instructions that handle proxified accesses to the stack. Byte-code look-aheads. Several byte-code instructions in our interpreter perform a look-ahead to avoid unnecessary instruction dispatches. This is the case for example of comparison instructions, that generate a boolean value by default, but skip modifying the operand stack and advances two instructions at a time if the following instruction is a branch instruction. Our implementation partially supports tracking constraints on the current method's byte-code, allowing one to generate byte-code sequences for the concrete execution, but requires extending it to symbolically lookahead byte-code in the instruction stream.

Constraint Solver Limitations. Doing a concolic execution of the VM requires a constraint solver that handles numbers with the same amount of precision as the VM. Indeed, the VM performs integer bound checks to apply safe arithmetics, detect potential overflow cases and the internal change integer representation. The constraint solver we are using supports (as for the time of writing this article) 56bit large numbers, and thus we constrained our usage for now to 32bit compilations. Other limitations of the constraint solver include the absence of bit-wise operations, which we overcome so far by abstracting the constraint model from the exact memory representation of objects (cf. Section 3.3).

Evaluation

In this section we evaluate our solution by the means of automatically testing the Pharo Virtual Machine JIT compiler. We first explain our evaluation methodology, and then follows a two-fold evaluation. On the one hand, we present and analyze our results applying interpreter-guided testing to a large set of the Virtual Machine byte-code and native method instructions. On the other hand, we evaluate the practicality of the approach by presenting time measurements of the concolic exploration and test execution time.

Evaluation Methodology

We evaluate our testing approach by applying it to the Pharo Virtual Machine JIT compiler. Our evaluation consists in four main experiments: (1) testing the IR-template compiler of native methods and (2-4) testing the three different byte-code to machine-code compilers, explained before in Section 4.1. Each test-case scenario found by the concolic exploration is executed on the JIT compiler using two different architectures: x86 and ARM32(v5-v7).

Time measurements for the second part of the evaluation were taken from machine with the following specs: 2015 MacBook Pro, 2,9 Ghz Intel Core i5, 16GB 1867 MHz DDR3. We report as time measurements averages with dispersion and totals for running all our tests. We did not run a thorough performance evaluation because we consider that the measurements are low-enough for practical usage, and performance is not at the core of this paper.

Results

Table 2 reports our results on top of the Pharo VM JIT compilers. Each line in the table reports the results for each of our compilers (column 1). The table shows the number of tested instructions (column 2), and how many execution paths were discovered by applying concolic testing on them (column 3). We semi-automatically curated the list of explored paths keeping only those paths that do work in our prototype implementation (column 4). The paths we removed paths are those not handled because of limitations of our prototype implementation: they either make our concolic execution to fail, they produce errors on the constraint solver, or they require special initializations on the JIT compiler we have not implemented in our testing infrastructure. Finally, we report how many of those paths present differences between interpreter and the JIT compilation, and the percentage they represent.

Analysis of Results

In this subsection we analyze the 468 path differences to identify its causing defect. We performed defect identification by manually inspecting and debugging the source code of the interpreter and the tested compiler. Because many paths do fail because of a same defect, we count a defect only once regardless of how many execution paths it lead to a failure.

Our testing approach detects six different categories of defects. We interpreted some differences as being caused by bugs in the interpreter or compiler (e.g., respective missing type-checks), while others are arguably correct in both and thus we interpreted them in a more neutral manner (e.g., behavioral differences). Table 3 summarizes all the defects causing the differences we found.

Most of the bugs found are in the byte-code front-end, and thus failed in both back-ends: ARM32 and x86. The first thing to notice is that native methods present more execution paths than byte-code instructions, shown in Figure 5, explaining why much more differences are found in native methods. Indeed, byte-code instructions present in average few more than 2 paths, while native method instructions approach 10 paths in average.

Missing interpreter type check. Type checks are missing in the interpreter, allowing some paths to execute on wrong conditions. Missing type checks, regardless of being in the interpreter or compiled code, produce unpredictable results and ultimately crashes at run time. This is the case of the primitiveAsFloat native method shown below. This native method checks the receiver type using an assertion that is removed at compile-time instead of explicitly failing the method execution. If the receiver is a pointer, its value will be coerced as an integer through pointer untagging, and then coerced to a double precision float, producing random numbers. Missing compiled type check. Type checks are missing in the compiled code, allowing some paths to execute on wrong conditions. As above, missing type checks produce unpredictable results and ultimately crashes at run time. For example, we have found that all floating-point related native methods (i.e., all arithmetics and comparisons) do not perform a type check on the receiver. The compiled code proceeds to unbox a double from the receiver's body producing a segmentation fault on the wrong receiver type.

Optimization difference. Optimizations exist on the compiler but not on the interpreter instruction, or vice-versa. Optimization differences do not produce incorrect executions as in the examples above, but raise the awareness of potential performance improvements. For example, our interpreter performs static type predictions on arithmetic byte-code instructions, inlining integer and float arithmetics [START_REF] Chambers | Customization: Optimizing compiler technology for self, a dynamically-typed object-oriented programming language[END_REF][START_REF] Holzle | Adaptive Optimization for Self: Reconciling High Performance with Exploratory Programming[END_REF] and performing a slower message-send only if types do not match the expectations. However, not all of our byte-code compilers implement the same: the simpler SimpleStackCogit implements no static type predictions, while the productive StackToRegisterMappingCogit and the experimental Regis-terAllocatingCogit inline only integer arithmetics but not floating point arithmetics.

Behavioral difference. The behavior differs in some way between compiled and interpreted code. For example, we have found that bit-wise operations on the interpreter fail with negative integers and fall-back to slower library code, while compiled code works both with positive and negative integers by treating both as unsigned integers.

Missing Functionality. Behavior is missing in the compiler or interpreter, not implemented and failing at run time with e.g., a not yet implemented exception. For example, we have found that several native methods introduced to accelerate FFI (Foreign Function Interface) memory and structure accesses were never implemented in the 32 bit compiler version.

Simulation Error. Error in our testing/simulation environment. Since our interpreter-guided approach is more exhaustive at testing that the pre-existing hand-written tests, it has found two different non-implemented paths in the simulation run time. These non-implemented paths are related to the simulation of invalid memory accesses: the simulation disassembles the failing instruction and performs a read-/write operation using reflection to call the corresponding register setter/getters. Our dynamic approach has found that some setter/getter methods reflectively called were missing, and thus difficult to detect by static analyses and lint quality rules.

Execution Time Analysis

To analyze the practicality of the approach, in this section we evaluate the different components that make the execution time. We identify two different kinds of run times: concolic execution run time, and test run time.

On the one hand, concolic execution run time, shown in Figure 6, is the time taken to concolically explore all execution paths of an instruction. Our measurements show that a single byte-code instruction takes in average ~600 ms to explore, while native methods take in average ~1700 ms. Total run time aggregates to 3 and 4.5 minutes respectively. It is worth noticing that most of this run time is taken by the constraint solver and a non-optimized AST-interpreter implementation, and that the results of the concolic exploration can be cached and reused multiple times.

On the other hand, test run time, shown in Figure 7, is the time taken to run all generated tests of a single instruction. Our measurements show that all the byte-code compiler tests take in average ~little above 30 ms, while native methods take in average ~little less than 100 ms. Total run times aggregates to ~10 seconds in total per set of tests.

Related Work

Several solutions have been proposed in the past to aid in testing and debugging programming language implementation validation, let them be Virtual Machines or compilers.

VM Simulation Environments and Meta-circular VMs. Meta-circular VMs and VM frameworks have offered for a long time simulation environments that helped in testing and debugging virtual machines. Such is the case of Self [START_REF] Ungar | Constructing a metacircular virtual machine in an exploratory programming environment[END_REF], Smalltalk [START_REF] Ingalls | Back to the future: The story of Squeak, a practical Smalltalk written in itself[END_REF][START_REF] Miranda | Two decades of smalltalk vm development: live vm development through simulation tools[END_REF] and Maxine [START_REF] Wimmer | Maxine: An approachable virtual machine for, and in, java[END_REF]. Our solution complements simulation environments with unit testing generation, generating tests that are unitary, fast-to-execute and exhaustive.

VM Testing. Maxine and Pharo reported recently QEMU based unit testing infrastructures for cross-ISA testing and debugging [START_REF] Kotselidis | Cross-isa debugging in meta-circular vms[END_REF][START_REF] Polito | Cross-ISA Testing of the Pharo VM: Lessons Learned While Porting to ARMv8[END_REF]. They reported that this infrastructures helped them in porting their VMs to ARMv7 and ARMv8 64bits respectively. Although their approaches are based on unit testing, they rely on manually written tests, while our approach performs automatic test generation. Lately, several work has explored the path of program fuzzing and differential testing between different Virtual Machines for a single language. Several work on the Java Virtual Machine (JVM) expose bugs via differential testing and bytecode fuzzing [START_REF] Chen | Deep differential testing of jvm implementations[END_REF][START_REF] Chen | Coverage-directed differential testing of JVM implementations[END_REF]. Moreover, test generation has been explored in the case of native extensions for the JVM (i.e., JNI) [START_REF] Hwang | Justgen: Effective test generation for unspecified jni behaviors on jvms[END_REF]. Similar work appeared recently for JavaScript engines, applying differential testing with test transplantation [START_REF] Lima | Exposing Bugs in JavaScript Engines through Test Transplantation and Differential Testing[END_REF] and compiler fuzzing [START_REF] Park | Jest: N+1-version differential testing of both javascript engines and specification[END_REF][START_REF] Ye | Automated conformance testing for javascript engines via deep compiler fuzzing[END_REF]. Although we share with these approaches the goal of automatic test generation, these explore a more coarse test generation using and usually think of the VM as a black-box. Our approach differs from these in several points: using the interpreter to guide the compiler testing helps us generating an exhaustive set of tests that are unitary. Indeed, our tests are fast to run and easy to debug. Additionally, one key aspect of our solution is that it is applicable in VMs that have a single implementation but many execution engines within it. Finally, our approach produces reproducible tests that exercise both the interpreter and JIT compilers, while the other approaches are subject to VM non-determinisms. Finally, some work report efforts to validate optimising compilers in an automatic and semi-automatic way [START_REF] Béra | Practical validation of bytecode to bytecode jit compiler dynamic deoptimization[END_REF][START_REF] Flückiger | Correctness of speculative optimizations with dynamic deoptimization[END_REF]. Although this is not the focus of this paper, we plan to extend our infrastructure in the future to test our optimising JIT compiler.

Compiler Testing. More broadly than VM testing, several work exist on the area of compiler testing and particularly on the automatic generation of test programs and oracles for their validation [START_REF] Chen | A Survey of Compiler Testing[END_REF]. Remarkable existing work cover random test generation solutions such as CSmith [START_REF] Yang | Finding and Understanding Bugs in C Compilers[END_REF], grammarbased solutions such as the work originated by Purdom [START_REF] Purdom | A sentence generator for testing parsers[END_REF] and mutation-based test generation such as equivalencemodulo-input (EMI) [START_REF] Le | Compiler validation via equivalence modulo inputs[END_REF]. Our approach differs from existing work in that most existing work treats compilers as black boxes, while our approach benefits from considering the interpreter as the language specification. In such manner, our approach quickly generates fast and relevant tests that exercise different parts on the JIT compiler and interpreter. [START_REF] Mckeeman | Differential Testing for Software[END_REF], where he showed how comparing different C compilers to find bugs in their differences.

Differential Compiler testing. Differential testing was introduced by McKeeman

They generate random test cases, depending on the level they test e.g., sequence syntactically correct C programs or type-correct C programs. Our approach extends traditional differential testing by comparing two essentially different execution engines: an interpreter and a compiler. Concolic Testing. Concolic testing [START_REF] Godefroid | Dart: directed automated random testing[END_REF][START_REF] Sen | Cute: A concolic unit testing engine for c[END_REF] is an automated testing technique that combines concrete and symbolic execution of a program to explore all of the program's possible execution paths. Traditionally concolic execution engines have been interpreter based, although recently they have been accelerated through compilation [START_REF] Poeplau | Symbolic execution with SymCC: Don't interpret[END_REF]. Our approach is so far implemented as a tree-walking AST interpreter, although, as shown in our evaluation, the execution times remain practical for its on-line usage. Instead, our current performance bottle-necks are in the constraint solver.

Conclusion

In this article we propose to guide the automatic unit testing of a JIT compiler by an interpreter definition based on two insights: first, we consider interpreters executable specifications of the programming language and second, both the interpreter and compilers for a language should implement the same language semantics. Based on these observations, our approach We first apply concolic testing on the interpreter to discover all possible execution paths and then validate the compiler using a differential testing approach.

We applied it to the byte-code interpreter and four different compilers of the Pharo Virtual Machine: both the native method template-based compiler and the stack-to-register byte-code compiler considered stable and in production since more than 10 years, plus two non-productive compilers. Our approach generated in less than 10 minutes more than 4.5K tests, and found 468 differences from 91 different causes. We show that interpreters are a valid resource when generating JIT compiler test inputs, unveiling many differences between them, ranging from clear bugs producing segmentation faults, to optimization and behavioral differences. Moreover, we show that the approach is practical and applicable on-line. In the future we plan to extend this work to generate minimal and relevant byte-code sequences for unit testing the JIT compiler.

1 Interpreter >> bytecodePrimAdd 2 |

 12 rcvr arg result | 3 rcvr := self internalStackValue: 1.

5 ( 7 " 8 (

 578 objectMemory areIntegers: rcvr and: arg) ifTrue: [ 6 result := (objectMemory integerValueOf: rcvr) + ( objectMemory integerValueOf: arg). Check for overflow" objectMemory isIntegerValue: result) ifTrue: [ objectMemory integerObjectOf: result).

1 .

 1 instructions created when compiling the byte-code instruction in Listing 1.

Figure 2 .

 2 Figure 2. Example of constraint tracking on the add byte-code. Each column illustrates one concolic path execution.Each concolic execution starts with an abstract input frame, and produces an abstract output frame, an exit condition, and the recorded constraint path. Already negated conditions are in italics. The last not-already-negated constraint path is negated and leads to the next concolic path execution.

Figure 3 .

 3 Figure 3. Constraint model. Constraint variables are grouped in abstract frames, objects and classes. Abstract objects model concrete objects and are interpreted to build concrete objects.

Figure 4 .

 4 Figure 4. Development environment of the Pharo VM. The VM is executed as Pharo code in the simulation environment and transpiled to C to produce the production artefact. The testing infrastructure extends the simulation environment.

1 ConcolicBytecodeTester 4 "

 14 Instantiate method and compile code 5 pushing elements to the operand stack" 6 cogit methodObj: self instantiateMethod.

12 13 "

 1213 Generate the instruction IR"14 descriptor := cogit generatorAt: bytecode.

  15result := cogit perform: descriptor generator.

16 17 "Listing 3 .

 16173 Generate a return instruction if necessary, 18 returning the result of the instruction" 19 solution exitCondition returnResultInto: self ] Intermediate Representation created when compiling the byte-code instruction in Listing 1

1 ConcolicNativeMethodTester

 1

9 10"Listing 4 .

 94 Generate a break instruction to detect fall-through cases" Intermediate Representation created when compiling the byte-code instruction in Listing 1

PL' 18 ,

 18 January 01-03, 2018, New York, NY, USA Guillermo Polito, Pablo Tesone, and Stéphane Ducasse

Figure 5 . 1 primitiveAsFloat 2 | rcvr | 3 rcvr

 5123 Figure 5. Paths per instruction. Byte-code instructions present in average few more than 2 paths, while native method instructions approach 10 paths in average.

4

  self assert: (objectMemory isIntegerObject: rcvr).

Listing 5 .

 5 Missing type-check in the interpreter primitiveAsFloat

Figure 6 .

 6 Figure 6. Concolic execution time per kind of instruction. Concolic execution per instruction, grouped by kind of instruction. Each data point represents the total execution time to concolically execute all paths of the instruction. Bytecode instructions have less execution paths and thus less execution time. Exploring instructions remains in the other of milliseconds for most instructions making them practical of on-line execution.

Figure 7 .

 7 Figure 7. Test execution time per kind of instruction.Test execution per instruction, grouped by kind of instruction. Each data point represents the total execution time to execute all generated tests for the instruction. Although native method compiler tests seem to have a higher average than byte-code compiler tests, they all remain below the 100ms bar.

Table 1 .

 1 Example of concolic execution paths obtained on the byte-code instruction in Listing 1. Each line in the table shows the concrete values fed as arguments, and the constraint path obtained for that exploration case.

		PL'18, January 01-03, 2018, New York, NY, USA				Guillermo Polito, Pablo Tesone, and Stéphane Ducasse
			Argument 0 (type) Argument 1(type) Path
	332		0 (integer)		0 (integer)	isInteger(arg0), isInteger(arg1), isInteger(arg0+arg1)
	333		0xFFFFFFFF (integer)		1 (integer)	isInteger(arg0), isInteger(arg1), isNotInteger(arg0+arg1)
	334 335 336		0 (integer) object1 (object) object1 (object)		object1 (object) 0 (integer) object2 (object)	isInteger(arg0), isNotInteger(arg1) isNotInteger(arg0), isInteger(arg1) isNotInteger(arg0), isNotInteger(arg1)
	337
	338
	339
	340
	341		Concolic Execution #1		Concolic Execution #2		Concolic Execution #3		Concolic Execution #4
	342
	343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361	Abstract Input Frame Abstract Output Frame + Recorded Path Constraints concolic execution Path negation	receiver = ? method = ? operand stack receiver = ? method = ? operand_stack_size <= 1 operand stack (empty) (empty) Exit: invalid frame	<<constraint solving + abstract frame construction>>	s3 > min small int) receiver = ? method = ? operand stack s1 = small int s2 = small int s3 = s1 + s2 receiver = ? method = ? operand_stack_size > 1 AND s1 is small int AND s2 is small int AND (s3 < max small int AND operand stack Exit: success	<<constraint solving + abstract frame construction>>	s3 <= min small int) s1 = max small int s2 = small int 1 s1 = max small int s2 = small int 1 receiver = ? method = ? operand_stack_size > 1 AND s1 is small int AND s2 is small int AND (s3 >= max small int OR receiver = ? method = ? operand stack operand stack Exit: failure	<<constraint solving + abstract frame construction>>	operand stack operand stack receiver = ? method = ? s1 = small int s2 = obj s1 = small int s2 = obj receiver = ? method = ? operand_stack_size > 1 AND s1 is small int AND s2 not small int Exit: failure
	362
	363	Negated	operand_stack_size > 1		operand_stack_size > 1		operand_stack_size > 1		operand_stack_size > 1
	364 365	Path Constraints			AND AND s1 is small int			AND AND s1 is small int		AND s1 not small int
	366 367 368 369				s2 is small int AND ! (s3 < max small int AND s3 > min small int)		s2 not small int		<<constraint solving + abstract frame … construction>>
	370
	371
	372
	373
	374
	375
	376
	377
	378
	379
	380
	381
	382
	383
	384
	385

Table 2 .

 2 Results running our approach on four different compilers. Number tested instructions indicate the explored interpreter instructions. Interpreter paths indicate the number of paths founds during the concolic execution. Curated paths indicate the number of paths supported by our implementation. Differences indicate how many of those paths differ between interpreter and compiler.

	Family	# Cases
	Missing interpreter type check	1
	Missing compiled type check	13
	Optimisation difference	10
	Behavioral difference	5
	Missing Functionality	60
	Simulation Error	2

Table 3 .

 3 Summary of found defects. Interpreter-guided testing finds differences including behavioural differences, missing type-checks leading to runtime errors and different optimized paths.

10

  Interpreter-guided Differential JIT Compiler Unit Testing PL'18, January 01-03, 2018, New York, NY, USA

		1000
	Time (ms) -log scale	100
		10
		Native Method	Stack-to-Register	Simple	Linear-Allocator
			Compiler

Acknowledgments

This work was funded by Inria's Action Exploratoire AlaMVic.


Audrey Hanan
email: audrey.hanan@univ-amu.fr

Isabelle Muratore
email: isabelle.muratore@univ-tln.fr

"Please, draw me an apple !": children's relationship with marketing

Keywords: transgression, food waste, reverse socialization, retailing, aesthetics

Please, draw me an apple !": children's relationship with marketing standards and "ugly" responsible products Several products are discarded by supermarkets because they are not matching with the aesthetically standardized criteria. Nevertheless, in an ecological perspective and for new business opportunities, supermarkets have recently decided to change their marketing norm in proposing a new offer called: "ugly products". This research focuses on children's receptiveness because they could become influencers and future consumers. A qualitative study has been performed resulting in 18 individual interviews and drawings of French children aged 8 to 12 years. Results highlight the existence of an implicit norm and the negative consequences of a rupture with it. This research helps to understand how this transgression of the aesthetic norm must be realized.

INTRODUCTION

Many authors have highlighted that retailers have means of influencing social and environmental sustainability (Ritch 2015), for example with organic products [START_REF] Wiese | Sustainability in retailingresearch streams and emerging trends[END_REF], labels [START_REF] Bezawada | What is special about marketing organic products? How organic assortment, price, and promotions drive retailer performance[END_REF] or sustainable transport and logistic [START_REF] Björklund | Exploring logistics-related environmental sustainability in large retailers[END_REF]). However, their aesthetic criteria today represent a significant food waste (15 to 30% prior to the commercialization process1 ). Some of these products are used to make soups, compotes, or fruit juices, but many do not find outlets2 . Thus, this aesthetic standard of retailers jeopardizes the sustainability of products and more precisely the reduction of food waste. In a context where consumers are expecting more responsible behavior, several retailers have decided to change this standard. Since 2014, supermarkets 3 propose a new offer of products called "ugly" (appendix 1). This offer (distorted and unsightly products) concerns different categories but mainly fruits and vegetables. [START_REF] Hanan | Le consommateur face à la transgression ordinaire de ses normes de consommation : le cas des produits alimentaires, Systèmes alimentaires-Food Systems[END_REF] have highlighted that regular customers reject these products even when they support the "no waste" approach. Thus, given the low level of interest in this more responsible standard, it is interesting to focus on the receptivity of children. The purpose is to know how an offer, which breaks the usual aesthetic standards of the supermarket for less food waste, is perceived by children and how to communicate on it. To answer this question, the psychological mechanism specific to the unaesthetic will be studied, as well as how to modify the value of these products.

The benefit of targeting children is threefold. Children constitute a primary market (the child is consuming), an influencing market (child influences the purchase of his/her parents) and a future market [START_REF] Mcneal | Children as a market of influencers[END_REF]. Studying children is very interesting as it remains easier to initiate habits very early in the consumer's life, rather than making those changes later.

Such childhood habits, in addition, become permanent as the consumers grow [START_REF] Moschis | Life course perspectives on consumer behavior[END_REF]. In concrete terms, children are to be considered here as potential actors of consumption (future consumers) as well as potential social actors (socialization agents) who can encourage this marketing change.

To do so, in the first part of this article we will give an overview of the pertinent literature concerning children sensibility to ecological problems, food aesthetic standards and socialization. After outlining the methodology, the results will be presented. Finally, discussion and contributions will be addressed.

CONCEPTUAL FRAMEWORK

Consuming "ugly products" represents a specific case among the measures to reduce waste, as it does not imply the throwing away (households' production of food waste) of what is in the refrigerator, but the involvement of oneself more precisely in a systemic perspective.

"Ugly products" are related to two different fields: ecology (food waste) and aesthetics.

Besides, it is important to specify that the child is characterized by the fact that he/she is in development [START_REF] Piaget | La psychologie de l'enfant, Que sais-je ?[END_REF], by a strong affective dimension and by socialization [START_REF] Ward | Consumer socialization[END_REF]. So considering children are acquiring skills, knowledge and attitude relevant to become consumers, ecology and aesthetics have to be investigated also from the socialization point of view.

Socialization

We are not born consumer, we become consumer. Thus even if the child is the subject of studies whose aim is to understand his/her influence, it is clear that the child learns standards of consumption. During childhood, socialization is the substratum of the future [START_REF] Moschis | Life course perspectives on consumer behavior[END_REF] During this period, socialization remains more structuring than during adulthood. [START_REF] Ward | Consumer socialization[END_REF] defines socialization as « processes by which young people acquire skills, knowledge, and attitudes relevant to their functioning as consumers in the marketplace ». The authors (e.g. [START_REF] Muratore | Children's deal proneness: elaboration of four measurement scales[END_REF]) consider that there several factors. Each of them generates a particular form of influence on the child'socialization: family, peers, media and school.

Regarding environmental socialization (i. e. the process of learning pro-environmental behaviours, through the acquisition of relevant skills, knowledge, and attitudes). Several studies in the field of the environment have shown that children's attitudes to environmental issues are influenced by their parents [START_REF] Ritch | Doing it for the kids: the role of sustainability in family consumption[END_REF]. However, it must be noted that parents' influence, when it exists, does not give the main explanation of environmental awareness [START_REF] Meeusen | The intergenerational transmission of environmental concern: the influence of parents and communication patterns within the family[END_REF]. This allows us to think that other agents of socialization play a major role.

Several recent studies (e. g. [START_REF] Meeusen | The intergenerational transmission of environmental concern: the influence of parents and communication patterns within the family[END_REF]) suggest that school may enhance the environmental knowledge of children, that in turn may affect their buying decisions. For [START_REF] Gentina | Environmentalism at home: the process of ecological resocialization by teenagers[END_REF], pupils who followed a program or a course related to environment, are significantly influenced by them. Their mothers are even more likely to think that school plays a major role in informing children about environmental issues. In addition to these courses, schools are implementing more and more environmental programs urging pupils to be eco-friendly (recycle, do not waste…). The reasoning is that if children behave this way at school, they will maintain this behaviour at home (through getting into a kind of routine or gaining conviction) and will in their turn be agents of socialization.

Nevertheless, according to Boeve de [START_REF] Boeve-De Pauw | The effect of eco-schools on children's environmental values and behavior[END_REF] pro-environmental programs implemented at school seem to increase children's environmental involvement more from a cognitive point of view than a behaviour one.

Resocialization

Even if studies concerning children's ecological resocialization present mixed results (Gronhoj and[START_REF] Gronhoj | When action speaks louder than words: the effect of parenting on young consumers' pro-environmental behaviour[END_REF][START_REF] Gronhoj | Like father, like son? Intergenerational transmissions of values, attitudes, and behaviours in the environmental domain[END_REF], recent ones seem to offer the same kind of results [START_REF] Gentina | Environmentalism at home: the process of ecological resocialization by teenagers[END_REF] which is that an ecological resocialization exists. Ecological resocialization refers to the process where parents learn from their children about proenvironmental consumption behaviour [START_REF] Larsson | Bringing environmentalism home: children's influence on family consumption in the nordic countries and beyond[END_REF]. Such a process of resocialization can be qualified as active (interaction) and/or passive (observation). [START_REF] Gentina | Environmentalism at home: the process of ecological resocialization by teenagers[END_REF] revealed that they "are active participants in decisions about household consumption in relation to pro-environmental issues. However, parenting style and the frequency of communication are clearly decisive to the extent of the kids' influence on pro-environmental parental consumption".

Aesthetic standards

The concept of aesthetics was not initially targeting manufactured products. Indeed, the ability to appreciate aesthetically a product implied the compulsory independence of considerations linked to its use. Marketing literature is generally assuming that the aesthetic value of a product has a positive impact on the global preference and the final choice of consumers [START_REF] Creusen | The different roles of product appearance in consumer choice[END_REF]. The determining role of sensory elements in the consumer's decision-making process (Jansson-Boyd and Marlow 2007), especially for food, can be explained by their impact on functional and symbolic representations of the product.

The visual aspect of the product conveys, for the consumer, information about the product's gustative quality. This reflex of the consumer is explained by the impossibility to taste food products before buying them.

The concept of incorporation (literally and etymologically "into the body") relates to the "magic thinking" dealt by anthropological studies related to food [START_REF] Fischler | Pensée magique et alimentation d'aujourd'hui[END_REF] and plays a fundamental role in eating. The consumerthe eaterconsiders that he or she acquires the properties of the food product: "we are what we eat" [START_REF] Rumiatti | We are what we eat: How food is represented in our mind/brain[END_REF] is part of the fundamental beliefs of our society. It is consequently not only about health, as Hippocrates mentioned, "let food be your first medicine", or about safety, but also about identity and selfconsciousness. These reactions are collective beliefs as valid among adults as children and transmitted via food socialization. Children will in this way acquire consumption standards, knowledge, tastes and food preferences transferred from parents, especially. Moreover, children learn eating practices thanks to social interactions "within different socialization contexts" (Hemar-Nicolas et alii. 2013). One context feeding another one. So children will also, through the phenomenon of reverse socialization, be the introducers of new products to their families [START_REF] Ayadi | An ethnography of the transfer of food learning within the family[END_REF]. These eating practices covering both nutritional, emotional and social experiences and contributing to the child food well-being (Hémar-Nicolas and Ezan 2018).

METHODOLOGY

Recruitment and tested product

A qualitative survey (semi-directive interviews and drawings) was conducted among 18 French children, aged 8 to 12. We chose children at the "concrete operational stage" (aged 7-12), as described by [START_REF] Piaget | La psychologie de l'enfant, Que sais-je ?[END_REF]. The participants were 10 boys and 8 girls and they live in France. It was important to define which would be the category of product in this study. Among products related to the offer of « ugly products », fresh products have been selected. This category has been represented by apples because the Agrimer study (2013) shows that French people buy more often fruits than vegetables (74% vs 56%), and that apples are more often chosen on a yearly basis. Children were selected according to their age, gender criteria, social category and consumption of apples. Particular attention was paid to verify not only that the selected children liked and consumed apples but also to check that "ugly products" have never been bought. The children were also not exposed to the advertising of "ugly" products. The interviews were between 60 and 75 minutes in length and were conducted privately at home in order to facilitate informant openness.

Proceedings

A semi-structured interview guide based on the Dimensional Qualitative Research (DQR) approach of [START_REF] Cohen | What qualitative research can be[END_REF] was achieved. Indeed according to [START_REF] Cohen | What qualitative research can be[END_REF] " DQR represents a comprehensive and systematic model for approaching and ultimately realizing the objectives typically set in a qualitative research" [START_REF] Cohen | What qualitative research can be[END_REF]. The DQR has been gradually applied according to the topics covered. For instance, the DQR has been declined through the theme of "apple" then of "the ugly apple" (without telling that it was an "ugly" product) then explaining what is an "ugly" apple (and so food waste, advertising about these products…).

So the DQR has been applied several times in the interview according to the topic involved.

Specifically, the interview focused on five dimensions (DQR), here are some examples presented according to the dimensions but not necessarily in the order of the interview guide.

Behavior: Tell me about your normal routine when you go shopping apples; Tell me about how you choose an apple?(...)Would you eat (buy, ask your parents to buy) this apple (ugly one)? ; Why ? (...) What do you do concerning food waste? (…) ; (cf. Imaginery) Would you buy (ask your parents to buy, eat) the apple that you want to sell? (…).

Affect: What do you think about this apple, what do you feel about it (a standardized apple and later an "ugly" apple)? (…); What do you feel concerning food waste?

Sensation and Imagery: Draw and describle the profile (his/her environment, car, job…) of the one who eats, buys this apple (the standardized apple then the ugly one)? (...); Now we are going to imagine "that you are a seller of "ugly " apples… ; What would you do in order to sell these ugly apples to your customers or friends? (What would you say…?).

Cognition: What is an ugly apple for you (perception: healthy, natural, ecological, harmful, good?); Have you heard about ugly apples, what do you know about that? Why are these apple different? For you, is this apple " ugly"? ; Why/ where are these apples sold? What should you tell your parents/friends in order to make them buy these apples (how ?)(…)

To meet the objective of this research, an approach mobilizing children's drawings was implemented. This projective method is particularly adpated to children who manage to express their thoughts better than through verbal expression.

Data analysis

Consistent with an exploratory approach, content analysis was achieved to identify themes in the interview narratives. In the initial stage, the two researchers have independently read each verbatim transcript to realize several coding. They have developed and refined categories of analysis then after a consensus about the categories they have independently coded all the interview transcripts. The researchers have discussed their codings and also their disagreements and finally have found a consensus.

RESULTS

To truly explore the representation of "ugly products", the first questions focused on the children's representation of a beautiful/not beautiful apple as well as on aesthetic habits.

Standardization is the norm

Children were requested to describe and draw their representation of: a beautiful apple vs a not beautiful one (Figure 1). Their distinction between the beautiful apple and the not beautiful one was clearly based on aesthetic dimensions more precisely on color and calibration. The beautiful was associated with perfect products, standardized and calibrated, whereas the not beautiful one was represented by bumps, different shapes, dark colors and associated with rottenness: "A beautiful apple is the red apple we can see in cartoons, it is a shiny apple" (Guillaume, 11 y.o.) ; "Its color must be homogeneous without marks." (Mateo, 12 y.o.). According to [START_REF] Nelson | Information and consumer behavior[END_REF], a difference can be made between research products and experience products. Research products are ones the quality and value of which for the consumer can be easily evaluated before being bought (e.g. the speed of a microprocessor), whereas experience products are ones the quality of which is difficult to evaluate before being bought and used or consumed. For these products, less easily to evaluate, we find the perception of risk (but children do not mention health risks and do not categorize it as an inedible product). These negative mental associations can be akin to beliefs.

Insert Figure 1

Thus, the question of an association between standardization and beauty should be raised. Several decades ago, the aesthetics of these products were probably perceived differently by children. The establishment of standards by retailers contributes to these new representations of beauty for children. Indeed, traditional food is defined [START_REF] Kühne | Innovation in traditional food products in Europe: Do sector innovation activities match consumers' acceptance?[END_REF] as a product which is regularly eaten, according to family habits (the usual food product). In this case, the traditional food for children is represented by the standardized product. The beauty is linked to a familiar universe; it is based upon pictures cumulated all over one's life [START_REF] Boulding | A consumer side experimental examination of signaling theory: Do consumers perceive warranties as signals of quality[END_REF]. To be clear when an apple is in the children's mind, it is necessarily a beautiful apple. Children associate the beautiful with a standardized product.

Standardization is the norm for food products. So, retailers through a homogenized offer have imposed aesthetic standards. Consequently, the not beautiful apple corresponds to an apple which breaks these aesthetic codes. So, standardization has an influence on the perceived typicality of the product. Thus, from a cognitive point of view, food and aesthetics are perceived as being strongly associated. Children want to buy what they are used to buying that is "the normal" product and leave the "not beautiful" for other people : "If I really have nothing else to eat then I shall eat this apple" (Eliott, 11 y.o.). An authentic product is opposed to the standardized offer [START_REF] Boltanski | Le Nouvel Esprit du Capitalisme[END_REF]. Consequently, not beautiful products could refer to the perception of authenticity, a decrease of aesthetics could be perceived as a reduction of pesticide, but results are only extremely marginally following such theory.

These reactions are very homogeneous. Only a very marginal case of children opposed authenticity to standardization. For them, the "not beautiful" is "good" for health [START_REF] Boltanski | Le Nouvel Esprit du Capitalisme[END_REF]. Consequently, not beautiful products could refer to the perception of authenticity, a decrease of aesthetics could be perceived as a reduction of pesticide. But results are only extremely marginally. This difference can be explained by the possession of a vegetable patch by their parents. "Perfect apples have pesticides, ungracious ones not.

Without pesticides, they risk malformation but they are better. Once, I had a kitchen garden, I had carrots, strange, stuck together… there was no pesticides" (Léo, 10 y.o).

We also perceive the effect of the aesthetic norm on the taste. When children have been requested to draw a good apple vs a not good one, they explain that their drawings would be like their drawings related to a beautiful and a not beautiful apple. In their comments, the good and the bad refer mainly to the functional approach of the product, especially their nutritional value (fresh or on the opposite unhealthy, musty, bacteriological) and their hedonic value related to pleasure (juicy, appetizing, soft or on the opposite too hard, too soft). Good and beautiful are linked with pleasure, health and well-being: "If the color is bright it means it will be juicy; I avoid big black marks, it means it is moldy inside" (Alexia, 8 y.o). Thus, the spheres of "beautiful and not beautiful" and the one of "good and not good" are extremely linked for children. Judgements are based solely upon affective/aesthetic dimensions instead of upon organoleptic quality: "A good apple is normal. That is beautiful" (Juliette, 9 y.o.).

Without information about the attributes, uncertainty is high regarding levels of attributes.

Consequently, aesthetics are a central discriminating attribute as they play a major role when buying or consuming the product. This is why it can be noticed that standardized products can be bought as impulsive purchases whereas "not beautiful" products tend to follow more complex patterns of informed purchasing decisions.

Two criteria were used by children to create a profile which corresponded to their mental picture: emotions of the character and their status. The buyer/consumer of the "ugly apple" is described with negative feelings such as sadness. These characters would either be without income or scientists who could understand these products: "An elderly person or a disabled person because as she is not as the others, she would take this apple which is not as the others too" (Jessica, 10 y.o). On the opposite, consumers of beautiful apple would be active people, rich and beautiful (figure 2):"He is one of us, a normal person" (Jessica, 10 y.o). These reactions highlight the lack of value for these new ecological products. The break with consumption codes reduce this product to a lower rank. These consumers intended for modest people. It is therefore essential to promote these products, by finding them a different positioning, so that they cease to appear like downgraded products.

Insert Figure 2

After, the interviewer explains that "ugly products" (that is the not beautiful ones) are anti wastage products, children understand that if they are not bought, they will be thrown away. From an ecological aspect, these products (from a no waste perspective) appear to show that children talk easily about parental socialization, school socialization and their own behaviour regarding wastage. However for them, food wastage consists only in finishing their plate because children, in other countries, are starving. Their anti-waste behaviour concerns both social and economic perspectives (it costs money to buy food). So, the involvement of "ugly products" in the case is less important because it is "indirect" food wastage. Indeed, it is the retailer who throws away or does not sell these products. So, individual responsibility is clearly less involved. Moreover, children do not make any link between waste and ecology.

The ecological aspect of these products doesn't seem to be a strong enough argument to launch a purchase decision whatever the gender: "No-wastage does not motivate me, concerning the apple because if I have to buy it, I will not eat it thus I am going to waste it" (Matéo, 12 y. o.).

The choice of conformity

What emerges from, it is that children do not break their parents' socialization standards, who themselves do not break the standards dictated by hypermarkets. Children identify what their parents consume and know perfectly what they themselves or their family appreciate or reject. This phenomenon is linked to an active or a passive socialization, parents explaining upstream which elements to look at when purchasing, or the child learning by observation what parents take into account for a purchase decision (Ayadi and Brée 2010).

Children's preferences, habits and norms are learned by socialization. According to them, their parents would make the choice of conformity by preferring the beautiful product: "My parents buy only what is beautiful, the opposite is not normal." (Jade, 11 y. o.)

The negative opinion of children towards the "ugly" products increases when the consumption of these products moves to other places of sociality (their school), where other interactants influence their choice, which refers to the normative influence of peers [START_REF] Khare | Role of green self-identity and peer influence in fostering trust towards organic food retailers[END_REF]. They express a negative attitude towards these products which is linked to an apprehension of being mocked by other children or perceived as different. Clearly, children's social well-being is in danger when they consume "ugly products". It has consequences on what they are and how they are perceived. They also explain that they would make the same judgment about a friend consuming such products. The food product is consumed for what it represents and what it involves in terms of social interactions and peer acceptance [START_REF] Ward | Consumer socialization[END_REF]. This is in accordance with several studies showing that peers have in particular a normative influence [START_REF] Bearden | Measurement of consumer susceptibility to interpersonal influence[END_REF] and that this influence is even more important when the product is consumed in public [START_REF] Ezan | Renforcer l'efficacité des actions de lutte contre l'obésité. Vers l'identification de leviers de persuasion spécifiques aux enfants[END_REF]. Such reactions recall how food contributes to the construction of social identities and also the concept of incorporation [START_REF] Rumiatti | We are what we eat: How food is represented in our mind/brain[END_REF]. Food consumed while being watched by others refers to the concept of self-extension [START_REF] Belk | Possessions and the extended self[END_REF]. What one owns is a reflection of one's identity. Even if identity construction is a lifelong process, childhood is a key moment. This refers to maintaining or enhancing their self-esteem [START_REF] Banister | Negative symbolic consumption and consumers' drive for self-esteem: The case of the fashion industry[END_REF] and also to the materialism concept, i.e. the importance that the consumer attaches to possession, and the belief that consumer goods and services provide the greatest source of satisfaction and dissatisfaction in life [START_REF] Belk | Possessions and the extended self[END_REF]:"I shall be perceived as a loser but I am not a loser. It is as if I was this strange fruit and I do not want to be perceived as strange. It is important to be normal as the others. With such a fruit I shall be ashamed. No, I will not bring this fruit at school" (Raphaël, 12 y.o).

More marketing and less ecological dimension

Taking into account that children's perceptions and intentions are not positive, children were asked to play the game of being directors of supermarkets in charge of selling "ugly products" to their friends. They are given main objectives: to reduce the perceived uncertainty linked to the evaluation of quality (cognitive dimension) and to improve the value of the product (affective dimension).

Their promotion through their price would be counterproductive because a price decrease would raise a concern regarding their quality and would make them look even less attractive compared to beautiful products. They also highlighted that the apple (for example) was different, rare (and not "ugly") and that rare products were more expensive:"If you say they are ugly, you must sell them for less, because you say they are not beautiful, but if you say they are special you should sell them as expensive or more" (Evariste, 10 y.o.).

Moreover, it seems important to further develop a cognitive communication for "ugly products", as they generate uncertainty. The brand name "ugly" must be rethought. For children, such a name does not represent these products which shall rather be represented through positive adjectives such as "special" or "original". They more often use terms such as "bizarre, distorted, different, strange, quirky". Conversely, for them ugly "is made to hurt"; "the apple is not ugly, it is not normal but it is not ugly". When choosing a food product, the perception of the product will certainly be affected by its sensory characteristics but also by a symbolism issued through extrinsic variables such as the brand name (Shifferstein 2001).

Concretely, here, children are pointing out the fact that even if the word "ugly" offends, once the interest has been aroused, children don't want to buy the product. This word contributes to raise its aestheticism and consequently the signals underlined upfront and related to quality issues. Moreover, it is not the usual way to sell a product. In fact, this "ugly apple" is considered as "different" and not "ugly" and it is not because it is different that it is not good whereas an "ugly" product will be "not good". The transcripts are convergent with Zajonc's research (1968). This deals with the familiarity with the product and the necessity to suppress differences not by stigmatizing them but, on the contrary, by putting these various products (beautiful and ugly apples) on sale together: "Imagine that there is a city of apples, all the same and that there is a strange one, it will be hated at the beginning, it won't be bought. But after a while, some people will reflect and will buy this apple, then they will explain why this apple is like that" (Noé, 12 y. o.); "In fact, it would be necessary to sell the "ugly" apple and the "not-ugly" one together in the same box" (Maëlle, 11 y. o.).

Besides, as children have expressed the need to taste the product, the experiential dimension of quality signs could be useful. This dimension describes information which conveys a guarantee on consumption experience, i.e. which informs the consumer of somebody else's judgement about the product. The quality meaning can be also indicated by a well-known and trusted agent of certification [START_REF] Caswell | Using informational labeling to influence the market for quality in food products[END_REF]. Concerning ugly products, statements by a nutritionist, a doctor or a well-known practitioner could increase consumer confidence. This kind of information source mainly reassures rather than giving subjective or objective information [START_REF] Lynch | Consumer evaluation of the quality of hospital services from an economics of information perspective[END_REF] :"I would offer them to be tasted" (Alexia,8 y.o. and Gwendal,8 y.o.);"Make advertisements with doctors or dietitians who explain the benefits of this apple" (Maeva, 12 y.o.). A certification label could increase the credibility of this offer. Official or not, it should allow consumers to be informed, to classify products and to be reassured. In this frame, efficient signal strategy can be implemented by producers if the latter are able to supply a credible information from the consumers' point of view : " I would have put a question: what does it change? It questions people. We do things by habit and we can change it" (Léo, 10 y. o.).

Persuasion or incitation techniques have also been suggested, notably the concept of associating fun elements to food products to attract children's attention and leading to impulse buys. This allows them to act as persuaders or deciders of parents' purchase decisions. The addition of fun, reinforcing hedonic elements, would attract the child, for instance scratch cards or presents [START_REF] Muratore | Involvement, cognitive development and socialization: three antecedents of the child's cents-off sensitivity[END_REF], or paradoxically offering beauty products when buying "ugly products": "We should offer something to push people to buy it. My friends, they would love to find beauty products (samples) or jewels (i.e. claire's brand)" (Ambre, 10 y.o).

If the ecological product is connected with a playful promotion adapted to children's expectations, the purchasing intention becomes possible and the ecological argument appears to be an additional benefit. In agreement with Monnot and Renou (2013), it is necessary to minimize the perceived constraint involved by ecological speech. It seems more relevant "to show the utility of ecological behaviour by valuing economical and practical arguments". So, it seems essential to think about these products, primarily, through a marketing axis and, secondly, an ecological dimension as an additional benefit. This allows children to ask for the "ugly product" through a more rational dimension (an ecological reason) to their parents and also to participate in their resocialization: "It is necessary to avoid that the farmer throws away (…). I did not know but it should be known. In fact, it would be necessary to put a lego gift in it and to say also that it is anti-wasting" (Evariste, 10 y. o.).

DISCUSSION

From a theoretical perspective, there is a real inference for children between standardization (aesthetic criteria), the taste and the quality of the product: the standardized product is linked to goodness. Moreover, a non-standardized product has less value than the standardized products, and the consumer of those products also has "less value" from a social point of view. This offer generates a feeling of misunderstanding. It is in contradiction with the aesthetic standards of the hypermarkets and the expectations of a perfect product. The perception of a non-conform aesthetic stimulus can generate the feeling of transgression for the consumer, which is a breach making consumers face the "unthinkable" or the "unexpected", a contradiction to a norm which is not consciously known by the consumer. Such a breach might lead to an alteration of the representation of the product and have an influence on the evaluation done by children. These variations might also be seen negatively (i.e. as losses). This is the reason why brands are usually focusing on incremental improvement operations, rather than on major changes. The conformity and symbolic dimension of consumption are significant and can have consequences for children, this is the result of a socialization phenomenom. The potential transgression, estimated here through a change of consumption habits, plays a role on the behavioral intentions. It induces, in this case, the perception of a product intended for people having a low income: a product for the poorest.

To consume such products which means transgressing aesthetic standards constitutes a double risk: first, the risk of the wrong taste and the wrong quality; secondly, the social risk coming from the social influence of peers' perspective, which is even more important for a child when building his/her social identity. That is why children do not want to buy them and prefer a standardized product, a normal product that they are used to buying.

Still from a theoretical aspect, all these points can deteriorate children well-being (Hémar-Nicolas and Ezan 2018). The study underlines that what is true for adults, is also true for children. In fact, socialization plays a main part in this phenomenon. Indeed, parents socialize their children according the inferences existing between the beautiful and the good, and peers socialize children from a social risk perspective.

From a managerial point of view, children have made suggestions for "ugly products" to be accepted. The aim for them is not to reduce the price which would confirm reduced quality but sales promotions through free gifts in order to raise interest in such products. According to [START_REF] Muratore | Teens as impulsive buyers: what is the role of price?[END_REF] promotional incentives can trigger impulsive buying. It is a relevant way to focus consumers' attention on emotionally appealing products. The deal should contribute to increasing the value of the product's image which is perceived as having a low value. This allows an increase in purchasing intentions, to increase the familiarity with the product, to test the product. The free-gift could lead to shape the behaviour and to change the perception of the product, raising awareness of "ugly products" amongst children who in turn become influencers and future consumers. This increase in the familiarity with the product [START_REF] Loebnitz | Who buys oddly shaped food and why? Impacts of food shape abnormality and organic labeling on purchase intentions[END_REF], contributing to decrease the initially perceived disruption and transgression, means that children can be more "sensitive" to this kind of product if they get used to seeing them in store. This point has to be studied because in France, these "ugly products" are more and more sold.

The word "ugly" makes children think about damaged, rotten or inedible food. So, this word "ugly" should not be used because they stigmatized the product, sending wrong cues concerning the product's quality. They feel that terms such as "strange", "special" will be more relevant in order to sell these products.

"Ugly" product communication should, in order to avoid the social risk perceived by the consumption of this type of product, integrate in its visual the friendly presence of peers group. This perspective is in line with the recommendations of [START_REF] Ezan | Renforcer l'efficacité des actions de lutte contre l'obésité. Vers l'identification de leviers de persuasion spécifiques aux enfants[END_REF], aiming to put not only a music (which could later be sing by the real peer group), a setting, a story, characters but also a group of peers.

From a societal perspective, even if children are socialized by parents and school concerning food waste in the home, they do not make a link between "ugly product", waste food and ecology. The field of food waste is not so clear. The link between "ugly products" and ecology is not so easy to make. So, it is necessary to engage in educational campaigns in order to understand what is food waste. In fact, if children think that it is not good to waste it is for two main reasons. On the one hand, it concerns an economic perspective (it costs), on the other hand, it deals with some kind of moral perspective. So, it is important to explain in a deeper way that wasting food is an ecological problem. This public policy recommendation is also called, more widely by [START_REF] Gruber | What a waste! Exploring the human reality of food waste from the store manager's perspective[END_REF] via "Awareness campaign: create understanding about natural resources necessary for food production". As mentioned in the review of literature, school (e. g. [START_REF] Gentina | Adolescent's influence on proenvironmental family decisions and resocialization processes[END_REF] seems to be the best socialization agent in order to enhance children's anti-waste knowledge explaining the ecological consequences of this phenomenon. Behaviourist actions have more impact than theoretical teaching in order to maintain behaviours in the supermarket context. The aim of such a socialization is to make them sensitive little by little without feeling any guilt. To be clear, if for them an "ugly product" is not synonymous with ecology. It seems important that such information (in a cognitive way) can be communicated by brands allowing the child to use this argument (while he/she wants products for the promotion which they contain) in order to convince his/her parents and indirectly to contribute to their resocialization.

School has a key role to play. These lessons can be part of the communication axes related to children food well-being (Hémar-Nicolas and Ezan 2018). Indeed, in a logic of well-being, school can intervene, of course, on the objective part of well-being in a transient and durable way. It deals with the importance of consuming fruits reminding the consequences of fruits on vitality and health. But, it is especially, the subjective dimension of well-being which need to be considered in order to make things change. School could demonstrate the organoleptic qualities of "ugly" product (by consuming them) in a transient way but also in a durable way through an altruistic perspective (that is to contribute to the planet well-being and so to feel well because of that). This subjective and durable part of well-being contributing to the eudemonism.

Finally, the fact that these teachings take place at school can modify the perceived social risk because peers would objectively have the same knowledge and could understand that buying such products is in fact a responsible and valuable behavior.

In the light of this new offer of "ugly products" to reduce waste, the school as a socialization agent may be a key-factor in countering the lack of awareness of adults in these products. Once aware of "ugly products", children could act as an influencer for this product category and modify their parents' behaviours as part of a reverse socialization.

Concerning limitations, two exist. On the one hand, the small size of the sample even if a semantical saturation has been reached. On the other hand, the exploratory perspective of this research. This aspect constituted the directions for further research. So, deeper investigations must happen concerning socialization about "ugly products". How to desensitize people from the aesthetic criteria established by retailers. An idea emanating from this research is, for instance, to work on the notion of difference. It would have also been instructive to delve more deeply into the explanation to "ugly food sensitivity". Gender, siblings, environment (countryside, city), self-esteem, materialism, ecological awareness, normative influence, well-being, parental occupation, country/cultural, should be investigated through their relationship with the intention of purchasing "ugly food". Moreover, in which way "ugly food" can result in positive effects on retailer perception also needs to be investigated.

  (…); Tell me what you know about reducing waste; From your point of view are the ugly apples related to food waste? Interpersonal relations: Have you ever talked about ugly apples with someone (friends, parents…how and why); Would you bring such an apple at school (why)?; What would you think if one of your friend bring such an apple at school ?(…) ; Are your parents/ friends/school talking about food waste with you (how, why, what, what do they do (…)?;

Figure 1 .

 1 Figure 1. A beautiful and a not beautiful apple: An example of a child's drawing

Despite their abnormal shape, they have the same quality as any other and have followed the same production process

In France, every year 17 football stadiums are wasted

The first supermarket was "Intermarché" then several retailers (Carrefour, Monoprix or Auchan) did the same.